- Reading Azure VM name, IP address, and hostname with PowerShell - Fri, Jul 28 2017
- Automating WSUS with PowerShell - Thu, Jul 13 2017
- Disable SSL and TLS 1.0/1.1 on IIS with PowerShell - Tue, Jun 27 2017
The PowerShell script discussed in this post is my solution.
$log = "C:\Temp\Approved_Updates.txt" $switch = "dev" $wsusserver = "wsus" [void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") $wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusserver,$False) $groups = $null if ($switch -eq "dev") { $groups = cat "C:\Temp\wsus_devDR.txt" } if ($switch -eq "prod") { $groups = cat "C:\Temp\wsus_PROD.txt" } if ($switch -eq "clients") { $groups = cat "C:\Temp\Wsus_Client.txt" } if ($groups -eq $null) { "No groups are presented" | Out-File $log -append return 0 } $updates = $wsus.GetUpdates() | ? {($_.CreationDate -gt "10/1/2013" -and $_.CreationDate -lt "11/1/2013" -and $_.Title -notmatch "Itanium" -and $_.Title -notmatch ".net Framework" -and $_.PublicationState -ne "Expired" ) -and ($_.ProductFamilyTitles -eq "Windows" -or $_.ProductFamilyTitles -eq "Office") -and ($_.UpdateClassificationTitle -eq "Security Updates" -or $_.UpdateClassificationTitle -eq "Critical Updates")} foreach ($group in $groups) { $wgroup = $wsus.GetComputerTargetGroups() | where {$_.Name -eq $group} foreach ($update in $updates) { $update.Approve(“Install”,$wgroup) } } "Approved updates (on " + $date + "): " | Out-File $log -append "Updates have been approved for following groups: (" + $groups + ")" | Out-File $log -append "Following updates have been approved:" | Out-File $log -append $updates | Select Title,ProductTitles,KnowledgebaseArticles,CreationDate | Out-File $log -append
Let’s go through the script line by line:
$log = "C:\Temp\Approved_Updates.txt"
The $log variable stores the location of the log file. We need the log file to check what updates were approved, when, and to which WSUS groups.
$switch = "dev"
I had to approve updates in stages to three client computer types—development (dev), production (prod), and then to all clients (clients). The corresponding groups exist on my WSUS server. With the help of the $switch variable, I determine which computer group I want to target.
$wsusserver = "wsus"
Here, I set up the variable that stores the WSUS server name:
[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") $wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusserver,$False)
In order to manage WSUS with PowerShell, I first load the WSUS snap-in and then connect to the WSUS server.
$groups = $null
This lines import a set of computer names which I store in the $group variable.
if ($switch -eq "dev") { $groups = cat "C:\Temp\wsus_devDR.txt" } if ($switch -eq "prod") { $groups = cat "C:\Temp\wsus_PROD.txt" } if ($switch -eq "clients") { $groups = cat "C:\Temp\Wsus_Client.txt" }
Here I check the value of the $switch variable to determine WSUS groups that I stored in text files, so I don't have to hardcode them in the script. Each line in the text file contains a WSUS group.
if ($groups -eq $null) { "No groups are presented" | Out-File $log -append return 0 }
Here I’m checking if groups were assigned to the $groups variable. If not, the script has nothing to work with and has to exit.
$updates = $wsus.GetUpdates() | ? {($_.CreationDate -gt "6/1/2016" -and $_.CreationDate -lt "7/1/2013" -and $_.Title -notmatch "Itanium" -and $_.Title -notmatch ".net Framework" -and $_.PublicationState -ne "Expired" ) -and ($_.ProductFamilyTitles -eq "Windows" -or $_.ProductFamilyTitles -eq "Office") -and ($_.UpdateClassificationTitle -eq "Security Updates" -or $_.UpdateClassificationTitle -eq "Critical Updates")}
Using the GetUpdates() method, I get the updates I’m going to approve from WSUS and store them in the $updates variable. As you can see, I have quite a few criteria for the updates: They have to be created between 6/1/2016 and 7/1/2016, shouldn’t be updates for computers with an Itanium processor (because we don’t have such computers). .Net framework updates should not be included (because they break some of our web clients). They should not be expired; they must belong to Windows or the Office product families and must be security or critical updates.
foreach ($group in $groups) { $wgroup = $wsus.GetComputerTargetGroups() | where {$_.Name -eq $group} foreach ($update in $updates) { $update.Approve(“Install”,$wgroup) } }
Now I’m looping through the groups that were stored in the $group variable. For each group name, I’m using the GetComputerTargetGroups() method to check whether the corresponding group exits in WSUS. If there is such group, I’m storing it in the $wgroup variable. Then I loop through all the updates stored in the $updates variable to approve and install them on the group stored in the $wgroup variable.
"Approved updates (on " + $date + "): " | Out-File $log -append "Updates have been approved for following groups: (" + $groups + ")" | Out-File $log -append "Following updates have been approved:" | Out-File $log -append $updates | Select Title,ProductTitles,KnowledgebaseArticles,CreationDate | Out-File $log –append
At the end of the script, I write information about the groups and approved updates into the log file using the Out-File cmdlet. With the help of the Select-Object cmdlet, I pick the information I’m interested in. This is what the log file looks like:
I believe that the below line should read:
This lines import a set of Computer Group names which I store in the $group variable.
or simply
This lines import a set of Group names which I store in the $group variable.
instead of,
This lines import a set of computer names which I store in the $group variable.
Get-WsusUpdate -Approval Unapproved | where {$_.Update.Title -like "*Preview*"} | Deny-WsusUpdate
start-transcript -path "C:\WSUSlogs\deny-wsus $(get-date -f dd-MM-yyyy).txt" -Append
Get-WsusUpdate -Approval Unapproved | where {$_.Update.Title -like "Feature update*"} | Deny-WsusUpdate
start-transcript -path "C:\WSUSlogs\deny-wsus $(get-date -f dd-MM-yyyy).txt" -Append
$dotnetupdates = Get-WsusUpdate -Approval Unapproved | Where {$_.update.title -ilike "*.NET Framework*" -or $_.update.title -ilike "*.NET*"}
$dotnetupdates | Approve-WsusUpdate -Action NotApproved -TargetGroupName "Windows10"
$dotnetupdates | Approve-WsusUpdate -Action NotApproved -TargetGroupName "Windows Server"
start-transcript -path "C:\WSUSlogs\deny-wsus $(get-date -f dd-MM-yyyy).txt" -Append
$AllUnaproved = Get-WsusUpdate -Classification All -Approval Unapproved -Status any
$AllUnaproved | Approve-WsusUpdate -Action NotApproved -TargetGroupName "Windows Server"
$AllUnaproved | Approve-WsusUpdate -Action NotApproved -TargetGroupName "Windows10"
$AllUnaproved | Approve-WsusUpdate -Action NotApproved -TargetGroupName "All without .net"
start-transcript -path "C:\WSUSlogs\deny-wsus $(get-date -f dd-MM-yyyy).txt" -Append
Hi here is mine but i need help about installing on the client pc
i run this and all was ok but i was thinking will only download on client pc(client – my coworkers in my company)
but not to install ….
Can u help me to tell me how to change with parametars only to download but not to install…
mario.kosev@gmail.com