Windows Update with PowerShell

We generally connect to backend servers via a jump-box or bastion host. On Windows this means RDP into the jump-box, then RDP from the jump-box to the backend server. However, recently a Windows update meant that the jump-box (which had the update) couldn’t RDP to the backend server (which hadn’t got the update). No RDP => no access to update the VM to restore RDP. Lots of fun!

In that case I managed to use Remmina from a Linux box to access the backend directly; however since we are going to hit this issue again we needed a better fix.

Cue PowerShell; this is deployed via Octopus so will work when RDP doesn’t. As an additional perk it means updating becomes much easier.



function Get-WIAStatusValue($value) {
    
    switch -exact ($value) {
        0 {"NotStarted"}
        1 {"InProgress"}
        2 {"Succeeded"}
        3 {"SucceededWithErrors"}
        4 {"Failed"}
        5 {"Aborted"}
    }
}

# Stop after any error
$ErrorActionPreference = "Stop";

# Whether an update requires a reboot
$needsReboot = $false;

# Since WU can be slow tell the user something is happening
Write-Host "Starting Update";

$UpdateSession = New-Object -ComObject Microsoft.Update.Session;
$UpdateSearcher = $UpdateSession.CreateUpdateSearcher();

Write-Host " - Searching for updates; this may take some time...";
$SearchResult = $UpdateSearcher.Search("IsAssigned=1 and IsHidden=0 and IsInstalled=0");
Write-Host " - Found [$($SearchResult.Updates.count)] updates to download and install";

foreach($Update in $SearchResult.Updates) {
    # Add Update to Collection
    $UpdatesCollection = New-Object -ComObject Microsoft.Update.UpdateColl;
    if ( $Update.EulaAccepted -eq 0 ) {
        $Update.AcceptEula();
    }
    $UpdatesCollection.Add($Update) | Out-Null;

    # Download
    Write-Warning " + Downloading update '$($Update.Title)'";
    $UpdatesDownloader = $UpdateSession.CreateUpdateDownloader();
    $UpdatesDownloader.Updates = $UpdatesCollection;
    $DownloadResult = $UpdatesDownloader.Download();
    $Message = " - Download {0}" -f (Get-WIAStatusValue $DownloadResult.ResultCode);
    Write-Warning $message;

    # Install
    Write-Warning " - Installing update";
    $UpdatesInstaller = $UpdateSession.CreateUpdateInstaller();
    $UpdatesInstaller.Updates = $UpdatesCollection;
    $InstallResult = $UpdatesInstaller.Install();
    $Message = " - Install {0}" -f (Get-WIAStatusValue $DownloadResult.ResultCode);
    Write-Warning $message;

    if ($installResult.rebootRequired) {
        Write-Warning " - Update requires reboot";
        $needsReboot = $true;
    }
}

if ($needsReboot) {
    Write-Warning "Rebooting following updates...";
    Start-Sleep -Seconds 10;
    Restart-Computer -Force;
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.