Script to pull all updates for a particular group in WSUS

Welcome Forums General PowerShell Q&A Script to pull all updates for a particular group in WSUS

Viewing 3 reply threads
  • Author
    Posts
    • #182730
      Participant
      Topics: 28
      Replies: 28
      Points: 163
      Rank: Participant

      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"}
      $group.GetSummaryPerUpdate()
      

      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.

    • #182742
      Participant
      Topics: 0
      Replies: 6
      Points: 43
      Rank: Member

      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.
      [void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
      $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
                  $serv
                  }
          }
      
    • #182760
      Participant
      Topics: 28
      Replies: 28
      Points: 163
      Rank: Participant

      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!

      • #182970
        Participant
        Topics: 0
        Replies: 6
        Points: 43
        Rank: Member

        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.

    • #182793
      Participant
      Topics: 0
      Replies: 6
      Points: 43
      Rank: Member
      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
      # https://xenappblog.com/2016/how-to-clean-up-wsus/
      # https://blogs.technet.microsoft.com/gborger/2009/02/27/what-to-do-when-your-wsuscontent-folder-grows-too-large/
      
      [String]$Computer = $env:COMPUTERNAME
      [Boolean]$useSecureConnection = $False
      [Int32]$portNumber = 8530
      $today = (get-date).ToString('MM/dd/yy')
      $OutFile = ".\DeclinedSupersededUpdates$today.txt"
      
      # Load .NET assembly
      
      [void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
      # Connect to WSUS Server
      $updateServer = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($Computer,$useSecureConnection,$portNumber)
      write-host "< <>>" -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
      $update.Decline()
      $count=$count + 1
      } # end of foreach update
      "{0} {1} {2}" -f $count, "superseded updates declined", $today |out-file -FilePath $OutFile -Encoding Ascii -Append
Viewing 3 reply threads
  • You must be logged in to reply to this topic.