How to make a report of missing Windows updates on Windows nodes?

I duplicated and edited the Application Monitor Template "Windows Update Monitoring" and would like now to create a report of the information I gather there (missing critical updates, missing normal updates, days since last restart and if a reboot is pending). Could someone please help me with that?

  • Add these to PowerShell script components, run on the remote system. We use SCCM to deploy, and like those status better, but you can use it as an example if you don't and just find our the WMI query for Software updates. 

    Here is the PowerShell we use to get pending restarts:

    Try {
    	$Test2 = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update'  Name 'RebootRequired' -ErrorAction SilentlyContinue
    } Catch {
    }
    Try {
    	$Test3 = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' -Name 'PendingFileRenameOperations' -ErrorAction SilentlyContinue
    } Catch {
    }
    If ($Test1 -or $Test2 -or $Test3) {
    	Write-host "Message.Restart: Pending"
    	Write-host "Statistic.Restart: 1"
    	Exit 2;
    } Else {
    	Write-host "Message.Restart: Not Needed"
    	Write-host "Statistic.Restart: 0"
    	Exit 0;
    }

    SCCM missing updates that have been assigned:

    #Get a list of all the missing updates according to CCM. Add -ComputerName to run on a remote system.
    $MissingUpdates = get-wmiobject -query "SELECT * FROM CCM_UpdateStatus" -namespace "root\ccm\SoftwareUpdates\UpdatesStore" | Where-Object {
    	$_.status -eq "Missing"
    }
    $MissingUpdates = $MissingUpdates | Where-Object {
    	$_.title -notlike "Security Intelligence Update for Microsoft Defender*"
    }
    $MissingUpdates = $MissingUpdates | Where-Object {
    	$_.title -notlike "Windows Malicious Software Removal*"
    }
    $MissingUpdates = $MissingUpdates | Where-Object {
    	$_.title -match (get-date -Format "yyyy-MM") -or $_.title -match ((get-date).AddMonths(-1)).ToString("yyyy-MM") -or $_.title -match ((get-date).AddMonths(-2)).ToString("yyyy-MM") -or $_.title -match ((get-date).AddMonths(-3)).ToString("yyyy-MM")
    }
    
    $MissingUpdates = $MissingUpdates.title | Sort-Object -Unique
    
    If ($MissingUpdates.Count -eq "0") {
    	Write-host "Message.Patches: No Missing Patches"
    	Write-host "Statistic.Patches: 0"
    	Exit 0;
    } Else {
    	$line = $MissingUpdates -join ", "
    	$Count = $MissingUpdates.Count
    	Write-host "Message.Patches: $line"
    	Write-host "Statistic.Patches: $Count"
    	Exit 0;
    }

    SCCM updates that have been tried and failed: 

    #Get all of the failed updates on the system
    $ListOfPendingUpdates = get-wmiobject -query "SELECT * FROM CCM_SoftwareUpdate" -namespace "ROOT\ccm\ClientSDK" | Select-Object Name, ErrorCode | Where {$_.ErrorCode -ge 13 -or $_.ErrorCode -eq 8 -or $_.ErrorCode -eq 9 -or $_.ErrorCode -eq 10 } 
    $ListOfPendingUpdates = $ListOfPendingUpdates.Name | Sort-Object -Unique
    
    If ($ListOfPendingUpdates.Count -eq "0") {
    	Write-host "Message.Patches: No Failed Patches"
    	Write-host "Statistic.Patches: 0"
    	Exit 0;
    } Else {
    	$line = $ListOfPendingUpdates -join ", "
    	$Count = $ListOfPendingUpdates.Count
    	Write-host "Message.Patches: $line"
    	Write-host "Statistic.Patches: $Count"
    	Exit 0;
    }

  • Thats very generous of you, but I already have my Powershell Scripts. I need now a report to get this values and show it to me for all servers.