Script to pull all updates for a particular group in WSUS

I recently installed WSUS for a smaller client, with ~ 150 servers in 4 main computer groups. This past month I had someone else on the team go through and approve the updates for each of these groups. Three of them should be the same (Prod, Non-Prod, and a “download and notify only” group), but the number of updates is off on one group by a significant amount. I thought to write a script that would pull updates by computer group so I could compare, but there doesn’t seem to be an easy way to do this. I tried the following:

$group = $sWSUS.GetComputerTargetGroups() | ? {$_.Name -eq "Non-Prod"}

But while this does return a list of updates, all of which show the Non-Prod ID in the ComputerTargetGroupID column, it returns a total of 2489 updates, which is everything approved on this WSUS server and about 100 more than is actually approved for this group. I am just curious why the discrepancy, and if anyone has a better way of defining a computer group and then pulling every update approved for just that group. In the WSUS console I can set an Update View that shows me this exact info, so there has got to be a way (I would think) to do it via PS.

This is what I have used before we switched away from WSUS. Tweak it as needed.

Param($TargetGroup="All Computers")
#Updates by server in a specific group
$SusServer = 'wsus01.domain.local'
$UseSSL = $False
$Port = 8530

# The below is to accommodate for WSUS 2.0 which has no standard UpdateServices module
# This can be accomplished easier and quicker using the WSUS 3.0+ standard update module.
$Wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer($SusServer,$UseSSL,$Port)

$updateScope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
# Other values for "IncludedInstallationStates" (All, Downloaded, failed, installed,
# installedpendingreboot, notapplicable, notinstalled, unknown)
$updateScope.IncludedInstallationStates = 'Downloaded','NotInstalled'

$ComputerTargets = ($wsus.GetComputerTargetGroups() | Where {$_.Name -eq $TargetGroup}).GetComputerTargets()
$Computertargets |
ForEach {
        $Computername = $_.fulldomainname.split('.')[0]
        $_.GetUpdateInstallationInfoPerUpdate($updateScope) |
        ForEach {
            $update = $_.GetUpdate()
            $serv = new-object PSObject
            $serv | add-member NoteProperty Computername $Computername.split(".")[0]
            $serv | add-member NoteProperty TargetGroup $TargetGroup
            $serv | add-member NoteProperty IsApproved $update.IsApproved
            $serv | add-member NoteProperty UpdateTitle $Update.Title

Thanks for the reply. This works, although it returns the updates approved for each computer (so 2453 updates approved for 125 computers in a group is going to return ~300,000 entries. I can certainly trim this down by just grabbing the approved updates from $ComputerTargets[0], so that gets me farther than I was. But I am surprised there is not an easier way to simply get the updates I have approved for the group itself rather than having to touch one of the members of that group. If (and I admit I don’t know why I would) I happened to have a group with updates approved but no members, I would not be able to run this. I can, however, see approved updates for an empty computer group through the console.

Nevertheless, this at least gets me started, thanks!

You may want to decline all updates that have been superseded. That may trim your update list.

# Change server name and port number and $True if it is on SSL

[String]$Computer = $env:COMPUTERNAME
[Boolean]$useSecureConnection = $False
[Int32]$portNumber = 8530
$today = (get-date).ToString('MM/dd/yy')
$OutFile = ".\DeclinedSupersededUpdates$today.txt"

# Load .NET assembly

# Connect to WSUS Server
$updateServer = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($Computer,$useSecureConnection,$portNumber)
write-host "<<<Connected sucessfully >>>" -foregroundcolor "yellow"
$updatescope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
$Updates = $updateServer.GetUpdates($updatescope ) |where {$_.IsSuperseded -eq 'True'} |sort ArrivalDate
$count = 0
foreach ($Update in $Updates)
[string]$date = $update.ArrivalDate
[string]$title = $update.Title
[string]$Bulletin = $update.SecurityBulletins
[string]$URLS = $update.AdditionalInformationUrls
"{0} {1} {2} {3} {4}" -f "Superseded Update: ",$date, $Title, $Bulletin, $Urls |out-file -filepath $outfile -encoding Ascii -append
$count=$count + 1
} # end of foreach update
"{0} {1} {2}" -f $count, "superseded updates declined", $today |out-file -FilePath $OutFile -Encoding Ascii -Append


I have not run that first script in a few years. I wish I had a WSUS server to run against to refresh my memory. But I think I was able to just report on a single update group by specifying it on the command line. The default is “All Computers”. Here I have a fictitious group called “2008 Servers”. Yes this could have been written more cleanly, but I was a noob at the time.

.\Report-WsusUpdatesByGroupServers.ps1 “2008 Servers” |Sort-object Computername | Export-Csv -notype |out-file .\MyApprovedUpdatesForGroup.csv

If you have no computers in an update group, you can not have approved updates for that group.