WSUS Reporting with Powershell Part 3

Edit: Find the complete script here.

This is the final installation that concludes WSUS reporting with PowerShell.  In part 1 I explained the basics of connecting to WSUS with PowerShell and making a few basic queries.  In Part 2 I covered using a specific group in WSUS and creating a summary of the updates that those group members needed.  In this post I’ll explain the following:

  • Filter the results to trim down the report.
  • Use HTML formatting to prepare an email.
  • Send the report via an HTML formatted email.
# Record the last time that WSUS was syncronized with updates from Microsoft.
$LastSync = ($wsus.GetSubscription()).LastSynchronizationTime

# Rewrite the array and eliminate servers that have 0 for needed updates.
$SummaryStatus = $SummaryStatus | where { $_.neededcount -ne 0 } | sort server

# List a summary of changes in a special table leveraging the "First" table class style listed above.
$WSUSHead += "<table class=`"First`">`r`n"
# Note the LastSync time.
$WSUSHead += "<tr><td class=`"First`"><b>Last Sync:</b></td><td class=`"First`"> " + `
$LastSync + "</td></tr>`r`n"
$WSUSHead += "</Body>`r`n"
$WSUSHead += "</Style>`r`n"
$WSUSHead += "</Head>`r`n"

# Create a generic HTML Header to use throughout the script for the body of the `
#  email message with table styles to control the formatting of any tables present it it.
$HTMLHead = "<Html xmlns=`"`">`r`n"
$HTMLHead += "<Head>`r`n"
$HTMLHead += "<Style>`r`n"
$HTMLHead += "TABLE{border-width: 1px;border-style: outset;border-color: `
black;border-spacing: 1px;border-collapse: separate;}`r`n"
$HTMLHead += "TH{border-width: 1px;padding: 1px;border-style:
inset;border-color: black;}`r`n"
$HTMLHead += "TD{border-width: 1px;padding-left: 3px;padding-right: `
3px;border-style: inset;border-color: black;}`r`n"
$HTMLHead += "TABLE.First{border-style: none;}`r`n"
$HTMLHead += "TD.First{border-style: none;}`r`n"
$HTMLHead += "</Style>`r`n"
$HTMLHead += "</Head>`r`n"
$HTMLHead += "<Body>`r`n"

# Build a variable with HTML for sending a report.
$UpdatesHTML = $HTMLHead
# Continue building HTML with the updates needed
$UpdatesHTML += $SummaryStatus | convertto-html -Fragment `
@{ Label = "Server"; Expression = { $_.server } }, @{ Label = "Needed Count"; Expression = { $_.NeededCount } }, @{ Label = "Not Installed"; Expression = { $_.NotInstalledCount } }, `
@{ Label = "Downloaded"; Expression = { $_.DownloadedCount } }, @{ Label = "Pending Reboot"; Expression = { $_.InstalledPendingRebootCount } }, @{ Label = "Failed Updates"; Expression = { $_.FailedCount } }, `
@{ Label = "Needed"; Expression = { $_.Needed } }

# Add an assembly to fix up powershell HTML markup. Ensures all special characters
# are converted correctly.
Add-Type -AssemblyName System.Web
$UpdatesHTML = [System.Web.HttpUtility]::HtmlDecode($UpdatesHTML)

# Create HTML email by adding all the various HTML sections from above.
$MailMessage = "

# Get the date and time.
$DateTime = Get-Date -Format "ddd MM/dd/yyyy h:mm tt"
# Set subject line to include the $DateTime variable.
$EmailSubject = "Update Status for " + $DateTime

# Send an email with all the compiled data.
[string[]]$EmailTo = ""
Send-MailMessage -To $EmailTo `
-Subject $EmailSubject -From "WSUS" `
-Body $MailMessage -BodyasHTML `
-SmtpServer "MailRelayServer"

An example of the WSUS Reporting HTML email output is below:

WSUS Reporting HTML Email

10 thoughts on “WSUS Reporting with Powershell Part 3”

  1. Can someone share a working version version of this script please? I combined code from all 3 parts of this WSUS report script but get multiple errors upon running in PS on WSUS server. I cannot even get connected to WSUS server and get MethodInvocationExceptions. I would like to cross reference a working script if possible. I can email my error output if needed. It would be great if I can get this working…Thanks :)

    • I can certainly share a working version of this and will post it. The script is intended to run on a management workstation or server and connect to an instance of WSUS. The first thing to do is to run:


      Make sure that the Microsoft.UpdateServices.Administration name space is present and up to date. I currently have version 2.0.50727 displayed in the output. If you can load the namespace, then try to make the connection to your WSUS server with:


      In the above, $true is saying that you want to use SSL. Double check that you can connect to WSUS from your web browser if you still cannot connect via PowerShell. If you have some generic errors you want to share post them in the comments, otherwise you can send me a message with the address on line 62 above.

    • I’ve added a new page with the fully working script. You will need to customize your WSUS connection parameters as well as the group id of the specific group you are trying to targe. Find it here.

  2. This is gr8! Thanks a bunch :) I posted a question on TechNet too and will submit your link as answer.

    I am running this on WSUS server and am successfully connected, however, get (shown in detail below) error “Cannot convert argument “0”, with value: “”, for “GetComputerTargetGroup” to type “System.Guid”: “Cannot convert null t
    o type “System.Guid”.”

    Now reviewing, I see after successfully processing $WSUS.GetComputerTargetGroups(),

    Error happens at:
    $ComputerTargetGroups = $WSUS.GetComputerTargetGroups() | Where {$ -eq ‘aa60f906-b555-4b81-bd3b-a050fde63ce8’}

    This is because I never changed GUIDs to ones from my WSUS. How to I adjust the code to get reports for all groups? How to choose groups selectively? Will I have to list all GUIDs?

    ERROR output from Windows PowerShell Transcript:
    UpdateServer Id Name
    ———— — —-
    Microsoft.UpdateServices.Internal.Ba… cedbf2-a30e-4f0d-82c8-008a8069f ABC
    Microsoft.UpdateServices.Internal.Ba… b7ed-5727-47f3-84de-015e03f688a Unassigned Computers
    Microsoft.UpdateServices.Internal.Ba… e97deb-848f-4d23-9709-084896736 DEF
    Microsoft.UpdateServices.Internal.Ba… ae9ba0-0604-4cec-a2eb-0a967ae3b GHI
    Microsoft.UpdateServices.Internal.Ba… 7c1c2-7ec7-4eed-a086-0b6067757a Blah Blah
    Microsoft.UpdateServices.Internal.Ba… 79eaf-397e-41ca-98-0df676767955 Test01

    Cannot convert argument “0”, with value: “”, for “GetComputerTargetGroup” to type “System.Guid”: “Cannot convert null t
    o type “System.Guid”.”
    At D:\Scripts\WSUS_Report_2.ps1:26 char:46
    + $MemberOfGroup = $wsus.getComputerTargetGroup <<<< ($ComputerTargetGroups.Id).GetComputerTargets()
    + CategoryInfo : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

  3. Further thoughts and maybe answering my own question, but I guess in order to process report for ALL WSUS groups would be get rid of pipe to ‘where’ qualifier?

    $ComputerTargetGroups = $WSUS.GetComputerTargetGroups()

    instead of

    $ComputerTargetGroups = $WSUS.GetComputerTargetGroups() | Where {$ -eq ‘aa60f906-b555-4b81-bd3b-a050fde63ce8′}

  4. Hey Scott,

    your script is exactly what I was looking for, thanks dude! But I’ve got a little problem with the result. The script runs without errors but the mail only consist of this:

    Last Sync: 08/01/2014 01:02:03

    Update Servers

    The table around “Update” and “Servers” has only two rows and two collums. The data is missing :( Do you habe any idea?

    I’m using Windows Server 2008 R2 with latest WSUS and PowerShell 1.0

  5. HI,

    I try to run this i PS and getting following error?
    PS C:\scripts> .\wsus1.ps1
    Unexpected token ‘First”>rn”‘ in expression or statement.
    At C:\scripts\wsus1.ps1:10 char:39
    + $WSUSHead += “rn” <<<rn”:String) [], ParseException
    + FullyQualifiedErrorId : UnexpectedToken


Leave a Comment