Important Notice: On February 29th, this community was put into read-only mode. All existing posts will remain but customers are unable to add new posts or comment on existing. Please feel to join our Community Discord for any questions and discussions.

Processing WindowsUpdateLog to monitor update progress

I'm providing these steps and code in the event it might be of use to others for monitoring longer Windows Update Services tasks such as the W10 to W11 22H2 upgrade.  While the process below is specific to the W11 22H2 upgrade if you follow the code it should be adaptable to remotely monitor other Update Services jobs.

  1. Create a manual collection in PDQ Inventory and add the target Windows 11-capable computers to upgrade to Windows 11.
  2. Create a computer group in Windows Update Services, add those same computers, and set the the corresponding W11 upgrade .e.g. "Windows 11 (consumer editions), version 22H2 en-us x64" or "Windows 11 (business editions), version 22H2 en-us x64" to Install for that computer group.
  3. PDQ Deploy a package that clears the SoftwareDistribution folder on the target computers:
  4. net stop wuauserv
    rmdir C:\Windows\SoftwareDistribution /s /q
    net start wuauserv
  5. PDQ Deploy a package using the PSWindowsUpdate PowerShell module to request available updates:
  6. Get-WUInstall -AcceptAll -IgnoreUserInput -Download -Install -IgnoreReboot -Verbose
  7. After PDQ Deploy package "completes" the install tasks (tasks generally take too long to complete but at least starts the process).  Check Windows Update Services console to see if the target computers have updated their status.
  8. In PDQ Inventory, selecting the computers in the manual collection, use the following PowerShell tool code get the computer's install progress:
  9. $Job = Start-Job -ScriptBlock {Get-WindowsUpdateLog}
    $Job | Wait-Job | Remove-Job
    $localPath = Get-CimInstance -Class Win32_UserProfile | select -Property SID, LocalPath, @{Name='Username';expression={((New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList $_.SID).Translate([System.Security.Principal.NTAccount])).Value}} | Where-Object { $_.Username -eq "$(whoami)" } | Select LocalPath -ExpandProperty LocalPath
    $logpath = "$localPath\Desktop\WindowsUpdate.log"
    if(!(Test-Path -Path $logpath -PathType Leaf)){
       "$(hostname): unable to find $logpath"
    } else {
        $log = get-content $logpath
        $winver = (Get-ComputerInfo).OsName -replace '\D',''
        if($winver -eq '10'){
            $jobids = @()
            $log | Select-String -Pattern 'Title = Windows 11 \((consumer|business) editions\), version 22H2 en-us x64' -Context 0,5 | select-object -First 1 | ForEach-Object {
                $lines = $_.Context.PostContext | Out-String
                $null = $lines -match "UpdateId = ([^.]+)"
                $updateid = $Matches[1]
                $log | Select-String -Pattern "Deployment job Id \S+ : NotifyClient .* called for update id $updateid" | ForEach-Object {
                    $null = $_ -match "Deployment job Id (\S+) : NotifyClient .* called for update id $updateid"
                    $jobids += $Matches[1]
                $jobids = $jobids | select -Unique
                if($jobids.Length -eq 1){
                    $step = "Download"
                } else {
                    $step = "Install"
                $jobid = $jobids[-1]
                $Matches = $null
                $perc = Select-String -Pattern "Deployment job Id $jobid .* Update progress, percent complete =" -Path $logpath | select-object -ExpandProperty Line -Last 1
                $null = $perc -Match "^(\d+/\d+/\d+ \d+:\d+:\d+).*percent complete = (\d+)"
                    "$(hostname): job id: found, job progress: $step phase is $($Matches[2])% complete."
                } else {
                    "$(hostname): job id: found, job progress: not found." # jobid found but no progress found
            } else {
                "$(hostname): job id: not found." # jobid not found
        } elseif($winver -eq '11') {
            "$(hostname): running Windows 11 now." # update previously completed and computer rebooted, no prior logs exist
        } else {
            "$(hostname): not running Windows 10 or 11." # update would not apply to different OS
  10. If you select all the computers in the tool's Run Mode window it will show a summary of the status for each.  For the computers reporting "job id: not found" you may need to repeat Step 6.  If the job is found but job progress isn't found, waiting some time and checking status again should yield results.
  11. Optionally, for those computers reporting "...Install phase 100% complete" and no current user session, remote control and choose "Update and restart" from the Power menu on the W10 lock screen to allow the PC to complete the upgrade.  Of course, that's optional since it will complete the install step on the schedule you set in the Windows Update GPO and/or if the current user chooses to complete the process sooner.
  12. After successful upgrade, move the computers in Update Services to another computer group and remove the computers from the manual collection in PDQ Inventory.