I have a powershell script that calls windows update to install updates and then restart the machine. The relevant part of the code is posted below:
if (-not $SkipUpdates) {
Write-ToLog -Message "Starting Windows Update process in background job..."
# Create scriptblock for Windows Updates
$updateScriptBlock = {
# Import the LogMail module at the start of the job
Import-Module "C:\Users\andyd\Desktop\System\LogMail" -Verbose
# Windows Update process
try {
$UpdateSession = New-Object -ComObject Microsoft.Update.Session
$UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
Write-ToLog -Message "Searching for updates..."
$SearchResult = $UpdateSearcher.Search("IsInstalled=0 and Type='Software'")
if ($SearchResult.Updates.Count -eq 0) {
Write-ToLog -Message "No updates found."
return $true
}
Write-ToLog -Message "Found $($SearchResult.Updates.Count) update(s)" -SendEmail
$UpdatesToDownload = New-Object -ComObject Microsoft.Update.UpdateColl
foreach ($Update in $SearchResult.Updates) {
$updateInfo = @(
"Title: $($Update.Title)"
"Description: $($Update.Description)"
"KB Article: $($Update.KBArticleIDs -join ', ')"
"Size: $([math]::Round($Update.MaxDownloadSize / 1MB, 2)) MB"
"Severity: $($Update.MsrcSeverity)"
"RebootRequired: $($Update.RebootRequired)"
) -join "`n "
Write-ToLog -Message "Found update:`n $updateInfo"
$UpdatesToDownload.Add($Update) | Out-Null
}
Write-ToLog -Message "Starting download of update(s)..."
$UpdateDownloader = $UpdateSession.CreateUpdateDownloader()
$UpdateDownloader.Updates = $UpdatesToDownload
$DownloadResult = $UpdateDownloader.Download()
$downloadStatus = switch ($DownloadResult.ResultCode) {
0 { "Not Started" }
1 { "In Progress" }
2 { "Succeeded" }
3 { "Succeeded with Errors" }
4 { "Failed" }
5 { "Aborted" }
default { "Unknown ($($DownloadResult.ResultCode))" }
}
Write-ToLog -Message "Download completed with status: $downloadStatus"
$UpdatesToInstall = New-Object -ComObject Microsoft.Update.UpdateColl
foreach ($Update in $SearchResult.Updates) {
if ($Update.IsDownloaded) {
Write-ToLog -Message "Ready to install: $($Update.Title)"
$UpdatesToInstall.Add($Update) | Out-Null
}
else {
Write-ToLog -Message "Failed to download: $($Update.Title)" -Level WARNING
}
}
if ($UpdatesToInstall.Count -eq 0) {
Write-ToLog -Message "No updates ready to install" -Level WARNING
return $false
}
# create restore point
Write-ToLog -Message "Creating Restore Point..."
Checkpoint-Computer -Description "WeeklyRestorePoint" -RestorePointType "MODIFY_SETTINGS"
Write-ToLog -Message "Installing $($UpdatesToInstall.Count) update(s)..."
$UpdateInstaller = $UpdateSession.CreateUpdateInstaller()
$UpdateInstaller.Updates = $UpdatesToInstall
$InstallResult = $UpdateInstaller.Install()
$successCount = 0
foreach ($index in 0..($UpdatesToInstall.Count - 1)) {
$update = $UpdatesToInstall.Item($index)
$updateResult = $InstallResult.GetUpdateResult($index)
$resultCode = switch ($updateResult.ResultCode) {
0 { "Not Started" }
1 { "In Progress" }
2 { "Succeeded"; $successCount++ }
3 { "Succeeded with Errors" }
4 { "Failed" }
5 { "Aborted" }
default { "Unknown ($($updateResult.ResultCode))" }
}
$updateStatus = @(
"Update Installation Details:"
" Title: $($update.Title)"
" Result: $resultCode"
" Error Code: $($updateResult.HResult)"
" RebootRequired: $($update.RebootRequired)"
) -join "`n"
Write-ToLog -Message $updateStatus -Level $(if ($resultCode -eq "Succeeded") { "INFO" } else { "WARNING" })
}
Write-ToLog "Update installation completed: $successCount of $($UpdatesToInstall.Count) succeeded" -SendEmail
return ($successCount -eq $UpdatesToInstall.Count)
}
catch {
$errorDetails = @(
"Windows Update Error Details:"
"Message: $($_.Exception.Message)"
"Type: $($_.Exception.GetType().FullName)"
"Stack Trace: $($_.ScriptStackTrace)"
) -join "`n"
Write-ToLog -Message $errorDetails -Level ERROR -SendEmail
return $false
}
}
# Start the job with all necessary parameters
$updateJob = Start-Job -ScriptBlock $updateScriptBlock
if (Wait-Job $updateJob -Timeout $UpdateTimeout) {
$updateResult = Receive-Job $updateJob
Remove-Job $updateJob
if (-not $updateResult) {
Write-ToLog -Message "Windows Update process completed with issues - Check log for details" -Level WARNING -SendEmail
if (-not $Unattended){
Write-Host "Waiting 60 seconds to allow reading of messages..."
Start-Sleep -Seconds 60
}
}
}
else {
Write-ToLog -Message "Windows Update process timed out after $UpdateTimeout seconds" -Level WARNING -SendEmail
Remove-Job $updateJob -Force
}
}
I have run it several times with the same output:
[2024-12-05 12:44:16] [INFO]:Found update:
Title: Windows 11, version 24H2
Description: Install the latest version of Windows: Windows 11, version 24H2.
KB Article: 5046617
Size: 91717.87 MB
Severity:
RebootRequired: True
[2024-12-05 12:44:16] [INFO]:Starting download of update(s)...
[2024-12-05 12:44:22] [INFO]:Download completed with status: Succeeded
[2024-12-05 12:44:23] [INFO]:Ready to install: Windows 11, version 24H2
[2024-12-05 12:44:23] [INFO]:Creating Restore Point...
[2024-12-05 12:46:00] [INFO]:Installing 1 update(s)...
[2024-12-05 12:46:08] [INFO]:Update Installation Details:
Title: Windows 11, version 24H2
Result: Succeeded
Error Code: 0
RebootRequired: True
[2024-12-05 12:46:08] [INFO]:Update installation completed: 1 of 1 succeeded
But the update does not seem to be applied (from System > About in Settings):
Edition Windows 11 Pro
Version 23H2
Installed on 10/10/2024
OS build 22631.4460
Experience Windows Feature Experience Pack 1000.22700.1047.0
The relevant entries from CBS.log that indicate the only failures at the time are:
2024-12-05 12:44:04, Info CBS Session: 31147795_1573414347 initialized by client WindowsUpdateAgent, external staging directory: (null)
2024-12-05 12:44:04, Info CBS InternalOpenPackage failed for Package_for_KB3025096~31bf3856ad364e35~amd64~~6.4.1.0 [HRESULT = 0x800f0805 - CBS_E_INVALID_PACKAGE]
2024-12-05 12:44:04, Info CBS Failed to internally open package. [HRESULT = 0x800f0805 - CBS_E_INVALID_PACKAGE]
2024-12-05 12:44:04, Info CBS Failed to create open package. [HRESULT = 0x800f0805 - CBS_E_INVALID_PACKAGE]
2024-12-05 12:44:04, Info CBS Failed to OpenPackage using worker session [HRESULT = 0x800f0805]
2024-12-05 12:44:04, Info CBS Session: 31147795_1573414348 initialized by client WindowsUpdateAgent, external staging directory: (null)
2024-12-05 12:44:04, Info CBS InternalOpenPackage failed for Package_for_KB3025096~31bf3856ad364e35~x86~~6.4.1.0 [HRESULT = 0x800f0805 - CBS_E_INVALID_PACKAGE]
2024-12-05 12:44:04, Info CBS Failed to internally open package. [HRESULT = 0x800f0805 - CBS_E_INVALID_PACKAGE]
2024-12-05 12:44:04, Info CBS Failed to create open package. [HRESULT = 0x800f0805 - CBS_E_INVALID_PACKAGE]
2024-12-05 12:44:04, Info CBS Failed to OpenPackage using worker session [HRESULT = 0x800f0805]