Windows Update from Specific date.

We had a pretty standard situation, wanted to patch a bunch of servers with all patches up to a specific date. Colleague and friend of mine created the below script which proved extremely helpful.

All credits to the below mentioned people.

NAME: update-installer.ps1
AUTHOR: Mads H. Larsen
Tested on PSversions: 2.0, 3.0

This script checks windows update for applicable updates to the system,
and then downloads and installs them. If you enter a date that is earlier
than todays date, only updates from that date or earlier are installed.

Most of the inner workings of the script is copied from:

I just added some code to compare the dates, check connectivity, show size
and elapsed time and do some formatting.
$runTime = [System.Diagnostics.Stopwatch]::StartNew()
Write-Host "Verifying connectivity, please wait..."
[string] $url = ''
[net.httpWebRequest] $req = [net.webRequest]::create($url)
$req.Method = "HEAD"

Try {[net.httpWebResponse] $res = $req.getResponse()}
Catch {Write-Host "$url is not available. Could not resolve $($url) " -foregroundColor red;return}
if (!($res.StatusCode -ge "200" -and $res.StatusCode -lt "400")) {Write-Host "$($url) is not available. HTTP StatusCode $($res.StatusCode)" -foregroundColor red;return}


function Get-WIAStatusValue($value)
switch -exact ($value)
0 {"NotStarted"}
1 {"InProgress"}
2 {"Succeeded"}
3 {"SucceededWithErrors"}
4 {"Failed"}
5 {"Aborted"}
$sw = New-Object System.Diagnostics.Stopwatch

$number = 0
$totalSize = 0
$totalDownloaded = 0
$needsReboot = $false

$date = Get-Date (Read-Host "Input target date ($((Get-culture).DateTimeFormat.ShortDatePattern))")

$updateSession = New-Object -ComObject Microsoft.Update.Session
$updateSearcher = $updateSession.CreateUpdateSearcher()

Write-Host " - Searching for updates"
$searchResult = $updateSearcher.Search("IsAssigned=1 and IsHidden=0 and IsInstalled=0")
$updates = $searchResult.Updates | Where-Object {($_.LastDeploymentChangeTime -le $date)}

Write-Host " - Found [$($updates.count)] updates to download and install"
if($($updates.count) -eq $null) {return}

$updates | Format-Table @{Expression={($_.LastDeploymentChangeTime).ToString(" dd-MM-yyyy ")};Alignment=”center”;Label="dd-MM-yyyy"},@{Expression={$_.KBArticleIDs};Alignment=”center”;Label=" KBID "},@{Expression={$_.MsrcSeverity};Alignment=”center”;Label="Severity "} -AutoSize
$totalSize = ($searchResult.Updates | measure-Object -sum MaxDownloadSize).Sum
Write-Host " ---------------------------------"
Write-Host (" = Total of {0:n2} MB to download`n" -f ($totalSize/1MB))

foreach($update in $updates)
# Add update to collection
Write-Host " [$(Get-Date -Format dd)-$(Get-Date -Format MM)-$(Get-Date -Format yyyy) @ $(Get-Date -Format HH):$(Get-Date -Format mm):$(Get-Date -Format ss)]"
$updatesCollection = New-Object -ComObject Microsoft.Update.UpdateColl
if ( $update.EulaAccepted -eq 0 ) { $update.AcceptEula() }
$updatesCollection.Add($update) | out-null
# Download
$size = $update.MaxDownloadSize/1MB
$size = "{0:N2}" -f $size
$totalDownloaded = $totalDownloaded + $size
Write-Host " + Downloading $number of $($updates.count) - $size MB:" $($update.Title)
$updatesDownloader = $updateSession.CreateUpdateDownloader()
$updatesDownloader.Updates = $updatesCollection
$downloadResult = $updatesDownloader.Download()
$message = " - Download {0}" -f (Get-WIAStatusValue $downloadResult.ResultCode)
if($sw.Elapsed.Seconds -lt 1){Write-Host $message "in less than 1 second"}else{Write-Host $message "in $($sw.Elapsed.Hours)h$($sw.Elapsed.Minutes)m$($sw.Elapsed.Seconds)s"}
# Install
Write-Host " - Installing update"
$updatesInstaller = $updateSession.CreateUpdateInstaller()
$updatesInstaller.Updates = $updatesCollection
$installResult = $updatesInstaller.Install()
$message = " - Install {0}" -f (Get-WIAStatusValue $downloadResult.ResultCode)
if($sw.Elapsed.Seconds -lt 1){Write-Host $message "in less than 1 second"}else{Write-Host $message "in $($sw.Elapsed.Hours)h$($sw.Elapsed.Minutes)m$($sw.Elapsed.Seconds)s"}
$needsReboot = $installResult.rebootRequired
if($needsReboot){Write-Host " One or more updates require a reboot to complete installation" -foregroundcolor "red"}

Write-Host -foregroundColor yellow "`n $totalDownloaded MB of updates downloaded and installed in $($runTime.Elapsed.Hours) hour(s) $($runTime.Elapsed.Minutes) minute(s) $($runTime.Elapsed.Seconds) second(s)."

Leave a Reply

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

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

Google photo

You are commenting using your Google 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.