If you quickly want to find out if a particular update has been installed on all of your machines, the built-in reporting of Windows Server Update Services (WSUS) is not really helpful. However, you can use PowerShell to create a WSUS update report.

Alex Chaika

Alex Chaika is a Microsoft Certified Solution Expert (MCSE) with more than 15 years of experience in IT systems engineering. He currently focuses on PowerShell and VMware PowerCLI.

I wrote the PowerShell script I describe in this post due to the recent unfortunate events when the WannaCry ransomware infected literally hundreds of thousands of computers. As usual, the main reason was that people didn't install security updates on time.

To check the state of all of our computers, I tried to use WSUS reporting. However, I quickly found out that the tool is not very flexible. Thus, it is extremely arduous to get the report for all machines even if you are looking for just one particular KB number. As you can see below, the report choices are pretty poor:

WSUS report console

WSUS report console

You need to create a report for every update of every operating system type. Imagine that you have many different Windows versions starting from Windows XP. It'll take you forever. Fortunately, you can use PowerShell to achieve your goal faster.

To simplify things a bit and enable reusing the same script in the future to produce reports for different KBs, I use a function that accepts the following parameters:

  • An array of strings for the KB numbers
  • A string for the WSUS server name
  • A string for the WSUS port number

To be able to run this function successfully, you need the Windows Update Services MMC snap-in installed. Otherwise you can run it on the WSUS server. Please note that by default, this function connects to the WSUS server using unsecured HTTP. If you're using SSL, you have to change the $False to $True in the line that initializes the $wsus variable.

I prepare the $report variable in advance, to be able to save the results into it later, and then I load the Microsoft.Update services assembly. Next, I initialize the following three variables:

  • $wsus: update services server object
  • $UpdateScope: WSUS update scope (list of updates on the WSUS server)
  • $CompSc: computer objects registered in WSUS

Next, I set up $UpdateScope.UpdateApprovalActions to "Install" because I'm interested only in those updates approved for installation.

I then start a foreach loop against the $kbnumber string array I intend to pass to the function. This provides all update objects that have the particular KB number in the title.

Inside the second loop, I'm using the update object's GetUpdateInstallationInfoPerComputerTarget method to get the status of the update for each computer object stored in $ComSc. To understand better how the GetUpdateInstallationInfoPerComputerTarget method works, take a look at the screenshot below:

WSUS update installation info per computer target

WSUS update installation info per computer target

The update status object contains the ComputerTargetId property, which is a unique GUID associated with each computer object. The GUID is the key that allows me to establish relationships between the update status objects and computer names.

In the third loop (ForEach object) I pass this GUID to the getComputerTarget method of the update service object (that the $wsus variable represents). This reads several properties of the computer object, such as computer name, IP address, and update status information. Below you can see an example of the WSUS computer object:

WSUS computer object information

WSUS computer object information

Next, I create a custom PowerShell object and store it in the $info variable. The properties of the $info object then contain the computer object properties and update the status properties I need for the report. The $report variable then stores an array of my $info objects.

After the loops execute, I filter the $report variable to remove all records where UpdateInstallationStatus is set to Installed, Not Applicable, and Unknown. The remaining records are the computers that require the updates with the KB numbers you specify when you call the function.

In the screenshot below you see a sample report:

WSUS updates report

WSUS updates report

At the end of the script, I added three arrays with the KB numbers that are critical for mitigating the vulnerabilities used for the recent WannaCry ransomware outbreak. I obtained information on the KB numbers from the following official sources:

Win the monthly 4sysops member prize for IT pros

Share
6+

Users who have LIKED this post:

  • avatar

Related Posts

7 Comments
  1. Paolo Maffezzoli 4 months ago

    Thanks Alex for this article, it can help to improve the Wsus reporting and investigation if and where is correctly applied a MS patch.

    0

  2. Lisandro da Silva 3 months ago

    Hi Alex

    Nice script! This is exactly what i'm looking for!

    I had some issues running this script.

    Could you provide me an explanation on how to use the script?

    Do you need to run this script on the WSUS server or can you do this remotely

    0

    • Author
      Alex Chaika 3 months ago

      You either need to run it on the WSUS server or on the server which has WSUS management console installed.

      0

  3. luciano 3 months ago

    hi when I run the script I get this error :

    Exception calling "GetUpdateServer" with "3" argument(s): "The underlying connection was closed: An unexpected error occurred on a receive."

    At line:8 char:1

    + $wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpda ...

    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : WebException

    You cannot call a method on a null-valued expression.

    At line:13 char:4

    + $updates = $wsus.GetUpdates($updateScope) | ?{$_.Title -match $kb} ...

    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo : InvalidOperation: (:) [], RuntimeException

    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.

    At line:13 char:4

    + $updates = $wsus.GetUpdates($updateScope) | ?{$_.Title -match $kb} ...

    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo : InvalidOperation: (:) [], RuntimeException

    + FullyQualifiedErrorId : InvokeMethodOnNull

    any ideas why?

    I'm using https (8531) and I changed this line  :

    getUpdateServer($wsusserver,$true,8531)

    any ideas how can I fix it ?thanks

     

    0

    • Author
      Alex Chaika 2 months ago

      If you are using self-signed certificate for your wsus server SSL please make sure that this certificate is added to the "Trusted Certificate Authorities" in the Certificates of the  computer you're running this script from.

      If the certificate you are using is from trusted CA, make sure that CAs certificate(s) are trusted (exist in the Trusted Certificate Authorities of the  computer you're running this script from).

      0

  4. Termid 3 months ago

    Hello Alex,

    first of all thanks for your work!

    I've pulled your code, saved it as .ps1 and ran on the WSUS Upstream Server with the elevated rights.

    at the end of the code you call your function and all looks good sofar, however genereated report file is just empty :-/ there is no single line... even no headers.

    and it doesn't give any errors back. Any Idea what it could be?

    Thanks in Advance!

    0

    • Author
      Alex Chaika 2 months ago

      If report file is empty it means that the loop which gets the updates info doesn't do its job. So' Id check that updates with KB numbers assigned to the arrays in the lines 35, 36, 37 are  downloaded to WSUS and approved.

      0

Leave a reply

Your email address will not be published. Required fields are marked *

*

CONTACT US

Please ask IT administration questions in the forum. Any other messages are welcome.

Sending
© 4sysops 2006 - 2017

Log in with your credentials

or    

Forgot your details?

Create Account