Downloads
125613.zip
ApproveUpdates-Improved Performance.ps1.zip

At a customer site, we use Windows Server Update Services (WSUS) to deploy product updates to computers in the network. Before WSUS will install product updates, you need to either manually approve them for installation or use the automatic approvals option, which doesn't allow you to choose which updates to install. It installs all of them. Recently, I needed to automate the process of approving a select group of product updates for installation. So, using the Microsoft Script Center's WSUS sample scripts as a guide, I created a PowerShell script named ApproveUpdates.ps1 that does the job.

ApproveUpdates.ps1 begins by loading RequiredUpdates.txt, which contains the title of each required product update, as Figure 1 shows.

After making sure this text file isn't empty, the script initializes the counters and log files it will use. In all, there are five logs: found.log, expired.log, approved.log, failed.log, and missing.log.

Next, ApproveUpdates.ps1 loads the Microsoft.UpdateServices.Administration assembly, which enables the script to use a Windows .NET Framework API to connect to a WSUS server. Specifically, it uses the AdminProxy class's GetUpdateServer method to retrieve an interface (of data type IUpdateServer) to the WSUS server and populates the $UpdateServer variable with that interface.

The IUpdateServer interface is used for two important tasks, as Listing 1 shows.

<strong>Listing 1: Excerpt from ApproveUpdates.ps1<br></strong>  <br># Get the All Computers group's GUID.<br>$updateServer.GetComputerTargetGroups() | foreach-object \\{ <br>  if ($_.Name -eq "All Computers") \\{$TargetGroupID = $_.id;\\}<br>\\}<br>$TargetGroup = $updateServer.GetComputerTargetGroup($TargetGroupID)<br># Get the updates from the WSUS server.<br>$updates = $updateServer.GetUpdates()<br><br><br>

First, the script uses IUpdateServer's GetComputerTargetGroups method to obtain the globally unique identifier (GUID) of the computer group for which the product updates will be approved (the All Computers group in our case). The $TargetGroup variable is populated with a reference to that computer group. Then, the script uses IUpdateServer's GetUpdates method to fill the $updates variable with a collection of the latest revisions of all the product updates in the WSUS database, including superseded and declined updates.

For each product update in that collection, ApproveUpdates.ps1 looks for a match in the RequiredUpdates.txt file. When a match is found, it records that product update in found.log. Next, the script checks to see if the product update is expired. If it's expired, the script adds it to expired.log. If it's not expired, the script tries to mark that product update as approved for installion in WSUS. If that operation succeeds, the script adds the product update to the approved.log. If that operation fails, it adds the update to failed.log.

After cycling through the collection, ApproveUpdates.ps1 compares the list of found product updates in found.log against the list of required product updates in RequiredUpdates.txt. When a product update is in RequiredUpdates.txt but not found.log, it means that the WSUS server is missing the update. Any missing product updates are recorded in missing.log.

Finally, the script displays the results on-screen. You can also check the log files for results.

If you use WSUS and you'd like to try ApproveUpdates.ps1, you can download the script by clicking the first Download the Code Here button near the top of the page. ApproveUpdates.ps1 requires PowerShell 2.0. You need to run the script from the directory where RequiredUpdates.txt is located.

AUTHOR'S NOTE: Reader Markus Köstler has suggested a modification to this script. I appreciate his constructive suggestion. I did modify the script using the searchupdates() function. However, it's not a matter of only replacing

$updates = $updateServer.GetUpdates()

with

foreach ($title in $ReqUpdatesFile) \\{<br>$updates = $updateServer.SearchUpdates($title)<br>  .<br>  .<br>  .<br>  \\}

Additional adjustments are necessary to accommodate the change. First, remove the If block that checks an update retrieved from WSUS database against a required update (line 50 in the original script). Second, there's no need for the code block that finds missing updates (line 76); instead, just add a new variable called $InstancesCount that counts how many instances of an update are found (if any). It can be used later to count and log missing updates.

I’ve added the updated code at the second Download the Code Here button above.