WSUS 2012: viewing superseded and superseding updates

I’ve shown over the last few months how Powershell can help manage a WSUS built-in a Windows Server 2012:

  • Problem

Now that Office 2010 SP2 has been released and that the catalog of my WSUS has been updated, I cannot filter anymore superseded Office 2010 updates with the following code:

# View superseded updates that were previously approved            
(Get-WsusServer).SearchUpdates("2010") | Where {            
 ($_.IsSuperseded) -and            
} |             
ft Title,SecurityBulletins,IsApproved,IsSuperseded -AutoSize 

If I run this, I got more than I expected:

I was just expecting bulletin MS12-34 being supersed by MS13-054 😦

It appears that the ‘IsSupersed’ property isn’t precise enough and that I need more information like the ones provided by the “Updates superseding this update” and the “Updates superseded by this update” properties that you can see in the above snapshot of the WSUS console.

  • Solution

The above search returns a collection of Microsoft.UpdateServices.Internal.BaseApi.Update objects.

Each object has many properties by default but not the aboves juicy ones (“Updates superseding this update”) I’m looking for.

That said, each object has also many methods that could help.

To get a collection of “Updates superseding this update”, the GetRelatedUpdates needs to be used according the following MSDN page on How to Get Update Details

How should I implement and use this method?

I can enumerate UpdateRelationship values and their meaning with this code:

[System.Enum]::GetValues([Microsoft.UpdateServices.Administration.UpdateRelationship]) | ForEach-Object -Process {
    '{0} -> {1}' -f ([Microsoft.UpdateServices.Administration.UpdateRelationship]::$_.Value__),$_

This step will just allow me to save some typing below…

Now the idea is to add on the fly a ‘UpdatesThatSupersedeThisUpdate’ property to each Microsoft.UpdateServices.Internal.BaseApi.Update object returned by the search.
This property should be filled-in with the collection of Titles returned by the GetRelatedUpdates method.
Let’s have a look at the changes I made to achieve this:

# View superseded updates that were previously approved            
(Get-WsusServer).SearchUpdates("2010") | Where {            
 ($_.IsSuperseded) -and            
} | ForEach-Object -Process {
    $_ | Add-Member -MemberType ScriptProperty -Name UpdatesThatSupersedeThisUpdate -Value {
    } -Force -PassThru
} | ? UpdatesThatSupersedeThisUpdate -notmatch "Service\sPack\s2" |
 fl Title,SecurityBulletins,IsApproved,UpdatesThatSupersedeThisUpdate 

I’ve added a foreach loop that processes each update object and adds a collection of titles of updates that superseded this update by first calling the GetRelatedUpdates method and then using an implicit foreach to return only the title property. The Add-Member cmdlet allows me to create this script property on the fly.

As this new scriptproperty is a multiline string, the match operator can be used to filter it.

I got only MS12-034 as a result, perfect that’s exactly what I was looking for 😎
MS12-034 is superseded by SP2 but SP2 isn’t the only update that supersedes MS12-034.

Note also that I’m actually using a feature of the match comparison operator. When used on multilines, it doesn’t return true or false.

This is what you can read with

Get-help about_Comparison_Operators

If the input is a collection, the -Match and -NotMatch operators return
the matching members of that collection, but the operator does not
populate the $Matches variable.

Did I already say that Powershell rocks!? 😀


5 thoughts on “WSUS 2012: viewing superseded and superseding updates

  1. I know this is an older post, but I am trying to use some of this logic to build a script that will search through all approved updates to find if there are any superseeding updates, if there are, and the superseeding update is approved, decline the superseeded update. This will help automate the declining of any updates which have been superseded, but have never superseded another update (icon with blue square at bottom) and updates which have been superseded and have superseded another update (icon with blue square in middle). This will help with keeping the WSUS storage to a minimum, in combination with the WSUS_Cleanup script which would then purge the physical files from the server. Can you help?

      • I just found your other post just before you replied, but it’s still not what I’m looking for.

        Expired Updates Declined: 0
        Obsolete Updates Deleted:5
        Updates Compressed:198
        Diskspace Freed:380447328
        Diskspace Freed: 0.35 GB

        Take update KB2536276 for example. After running that cleanup, it still exists as an Install approval, but yet KB3000483 is superseeding this update, and is approved for install. Subsequently, KB9800232 is superseeded by KB2536276 and is also set to install. KB2536276 and KB9800232 are old updates that should be removed/declined. If I look at KB3000483, at least in my case, all computers are set to not applicable, so it has been installed on every computer making KB2536276 and KB9800232 extra disk space on my server.

        I run a cleanup script daily to clean it up ( (going to adjust it based on your nicer output of Diskspace Freed – Thank you), but this still leaves me with the middle and ending superseeded updates approved. Please read through the answer in

        I’m trying to build a powershell script to do this – well the 2nd part where he starts “To SEARCH for superseded updates…”

        Then I was going to elaborate on the script to include his first part of his answer – if it were possible, but the 2nd part is the main thing that I wanted to script because this saves HUGE on disk space (225GB when not doing it, to 74GB with doing it), at least for me initially when I did my initial clear out.

    • Ok, I understand what you want to do:

      On my latest article on this page remove the line that checks if the update is approved or not on step 1.

      You should have

      # Create an update scope
      $UpdateScope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
      # by default the update scope is created for any approval states
      $UpdateScope.ApprovedStates -eq 'Any'
      # Get all updates
      $allupdates = (Get-WsusServer).GetUpdates($UpdateScope)
      # See how many updates you've
      # comment the line that checks if the update is approved or not
      # as you don't care
      # First count them
      $allupdates | Where  {
      ($_.IsSuperseded) -and  
      # -not($_.isApproved) -and 
      } | Measure
      # 2. Have a look at their title, just in case
      $allupdates | Where  {
      ($_.IsSuperseded) -and  -not($_.isDeclined)
      } | Select Title
      # Decline these updates
      $allupdates | Where  {
      ($_.IsSuperseded) -and
      } | ForEach-Object -Process {            

      Before doing this, make sure you’ve a backup of your WSUS server.
      And if you’ve a test environment, pls test it there before going into production just to validate that it does what you want.

  2. This worked for me, but at the same time, it has no checks and balances, and since I’m diligent in my approvals, this did work as expected. All you’re doing is declining any update that is not already declined and is superseeded. So what if the update that superseeds has not yet been approved.

    I’m trying to build a powershell script that will

    1. Find a superseeded update that is not declined
    2. Verify that the superseeding update is approved (thereby making this one null and void)
    3. decline the superseded update.

    You’ve got me to 1 and 3 so far, but the biggest check that’s needed is number 2, as the script you presented would not care if it’s superseeding update is approved or not.
    I was trying to use the following as reference material, but my powershell is not as advanced.

    Thanks for all your help, and you will be mentioned in my script when I release it with a link to your blog.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s