Get Missing Updates with PowerShell and MBSA

Adam Bertram

Adam Bertram

Read more posts by this author.

I come across all kinds of situations these days where I think back to myself “Man, this would have been SO much easier with PowerShell!”. I just had one of those moment today.

I had a need to find all updates that were missing from a group of computers. Back in the day when I didn’t have SCCM, I used Microsoft’s HFNetChk tool; yea, it’s been that long. I remember having to scan dozens of machines and then figure out how to best merge all that data together. It was a nightmare!

This time I leveraged my PowerShell kung-fu to whip a tiny little function to point at a computer and find all the missing updates. This one’s not quite the level that I normally like to share but it gets the job done well.

Download this script on the Technet Script Repository

function Get-MissingUpdates { 
    param ( 
    begin { 
        function Get-32BitProgramFilesPath { 
            if ((Get-Architecture) -eq 'x64') { 
                ${ env:ProgramFiles(x86) } 
            } else { 
        function Get-Architecture { 
            if ([System.Environment]::Is64BitOperatingSystem) { 
            } else { 
        $Output = @{ } 
    process { 
        try { 
            ## Remove any previous reports 
            Get-ChildItem "$($Env:USERPROFILE)\SecurityScans\*" -Recurse -ea 'SilentlyContinue' | Remove-Item -Force -Recurse 
            ## Run the report to create the output XML 
            $ExeFilePath = "$(Get-32BitProgramFilesPath)\Microsoft Baseline Security Analyzer 2\mbsacli.exe" 
            if (!(Test-Path $ExeFilePath)) { 
                throw "$ExeFilePath not found" 
            & $ExeFilePath /target $ComputerName /wi /nvc /o %C% 2>&1> $null 
            ## Convert the report to XML so I can use it 
            [xml]$ScanResults = Get-Content "$($Env:USERPROFILE)\SecurityScans\$($Computername.Split('.')[0]).mbsa" 
                        $UpdateSeverityLabels = @{ 
                '0' = 'Other' 
                '1' = 'Low' 
                '2' = 'Moderate' 
                '3' = 'Important' 
                '4' = 'Critical' 
            $MissingUpdates = $ScanResults.SelectNodes("//Check[@Name='Windows Security Updates']/Detail/UpdateData[@IsInstalled='false']") 
            foreach ($Update in $MissingUpdates) { 
                $Ht = @{ } 
                $Properties = $Update | Get-Member -Type Property 
                foreach ($Prop in $Properties) { 
                    $Value = ($Update | select -expandproperty $Prop.Name) 
                    if ($Prop.Name -eq 'Severity') { 
                        $Value = $UpdateSeverityLabels[$Value] 
                    $Ht[$Prop.Name] = $Value 
        } catch { 
            Write-Error "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" 

Subscribe to Adam the Automator

Get the latest posts delivered right to your inbox

Looks like you're offline!