Monday 3 December 2018

Get Windows Update status

The following PowerShell code was developed to retrieve Windows Updates that had the status 'In Progress Installing'. The purpose of which was to later help develop a Restart Popup that could acknowledge when a PC needed a restart, to finish installing these updates, after a set number of days. The script looks for 3 specific status codes in order to do this (Get-WmiObject), then passes any found through to ComObject so that a date can be retrieved.

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Function Get-WindowsUpdateStatus {
<# .SYNOPSIS
Retrieves information on local windows updates with status 'In Progress installing'.
.DESCRIPTION
Get-WindowsUpdateStatus retrieves a list of local windows updates filtered via
'ResultCode 1' for 'In Progress installing' and the source 'CcmExec' or 'AutomaticUpdates'.

.EXAMPLE
Get-WindowsUpdateStatus
.EXAMPLE
Get-WindowsUpdateStatus | Where-Object { ($_.Date -le (Get-Date).AddDays(-1)) }
#>

[CmdletBinding()]
Param()
    BEGIN {}
    PROCESS {
        
        Try {

            ## Look for windows updates with status: 8 (pending soft reboot), 9 (pending hard reboot), 10 (wait reboot)
            $CCMUpdate = Get-WmiObject -Query 'SELECT * FROM CCM_SoftwareUpdate' -Namespace 'ROOT\ccm\ClientSDK'  | Where-Object { $_.EvaluationState -eq 8 -or $_.EvaluationState -eq 9 -or $_.EvaluationState -eq 10 }
            ## Checks a windows update is found before proceeding
            $CCMUpdateCheck = If(@($CCMUpdate).length -ne 0) { $True } Else { $False }

            #If an update is found
            If ($CCMUpdateCheck) {
                
                #Cycle through each one
                ForEach ($update in $CCMUpdate) {
                    
                    $updatename = $update.Name
                    Write-Verbose -Message "WmiObject Windows Update pending reboot found Name: '$updatename' passing through to ComObject"

                    ## WmiObject finds a windows update, now ComObject can acquire the date for 'Cumulative update' only. ResultCode '1' = In Progress installing.
                    $Session = New-Object -ComObject "Microsoft.Update.Session"
                    $Searcher = $Session.CreateUpdateSearcher()
                    $historyCount = $Searcher.GetTotalHistoryCount()
                    $ComObject = $Searcher.QueryHistory(0, $historyCount) | Where-Object { ($_.ResultCode -eq '1') -and ($_.Title -match $update.ArticleID) -and ($_.Title -notmatch 'Adobe Flash Player' ) -and ($_.ClientApplicationID -eq 'CcmExec' -or $_.ClientApplicationID -eq 'AutomaticUpdates') }
                    
                    If ($ComObject) {
                        $ComObjectTitle = $ComObject.Title
                        $ComObjectDate = $ComObject.Date
                        Write-Verbose -Message "ComObject Windows Update pending reboot found Name: '$ComObjectTitle', Date/Time: '$ComObjectDate'"
                        $ComObject
                    }
                    Else {
                        Write-Verbose -Message "No ComObject match for Name: '$updatename'"
                    }

                }
            }
            Else {
                Write-Verbose -Message 'No WmiObject Windows Update pending reboot found, nothing to pass through to ComObject'
            }

        }
        Catch {
            Write-Verbose -Message 'The following error occurred'
            Write-Verbose -Message $_
        }

    }

    END{}
}
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

Get Windows Update Status.ps1

No comments:

Post a Comment