Last week, I accidentally built a function which downloads update files from Microsoft Update Catalog. What is its real-life application?
Say you are building an OS installation image from scratch, which will then be deployed en masse. Common approach is to integrate all available updates into such image, to increase security and decrease post-installation tasks duration.
For Windows Server 2012 R2 and earlier OSes you have to download and integrate dozens of updates, but you are not sure which ones are required for your installation image (Windows Server 2012 R2 ISO-image has been rebuilt at least three times). The only way to determine which updates to integrate is to install a fresh computer from an ISO-image, connect it to the Internet and check for updates from Microsoft Update.
We can script it as follows:
1 2 3 |
$Criteria = "IsInstalled=0 and Type='Software'" $Searcher = New-Object -ComObject Microsoft.Update.Searcher $SearchResult = $Searcher.Search($Criteria).Updates |
$SearchResult object will contain a list of updates which your machine requires.
To integrate those updates, you need to receive their .msu or .cab files. Unfortunately there is no way (at least known to me) to extract download links from the $SearchResult object. Here’s where the new Get-WUFileByID function comes to help:
First, you have to get a list of KB IDs from the $SearchResult object:
1 2 3 4 5 |
[string[]]$KBIDs = '' ($SearchResult | Select-Object Title).Title | ForEach-Object { $null = $_ -match '^.+\(KB(\d+)\)$' $KBIDs += $matches[1] } |
Then you just pass each one of these to the function and it will download the files:
1 2 3 |
foreach ($ID in $KBIDs) { Get-WUFileByID -KD $ID -SearchCriteria 'Windows Server 2012 R2' } |
In the -SearchCriteria parameter, specify a product for which you need to download updates.
As the result, updates will be downloaded to the current catalog (you can redirect them with -DestinationDirectory parameter).
At last, integrrate the updates with help of Add-WindowsPackage cmdlet.
If you do not want to download any files, but wish to receive links only, -LinksOnly switch is here just for that!
The function is covered by tests and available at GitHub. Should you have any questions of suggestions, feel free to leave them in the comments section or raise an issue.
Hello Kirill,
How about the following approach for downloading/getting links to the update cab files?
These cab files could be added to offline image by dism
#$Criteria = “IsInstalled=0 and Type=’Software'”
#$Searcher = New-Object -ComObject Microsoft.Update.Searcher
#$SearchResult = $Searcher.Search($Criteria).Updates
foreach ($update in $SearchResult) {
$title = $update.Title
$guid = $update.Identity.UpdateId
$title
$guid
$bundles = $update.BundledUpdates
foreach($bundledUpdate in $bundles) {
foreach($content in $bundledUpdate.DownloadContents) {
if (!$content.IsDeltaCompressedContent) {
$url = $content.DownloadUrl
$url
}
}
}
}
Hi Dmitry!
Well, as I stated earlier: “Unfortunately there is no way (at least known to me) to extract download links”.
Now I know! Thanks man, I will use that method.
Also, the function is still useful when you want to download files for a specific update.
Is there a way to modify this so that i can search without a KB#?
I need to get the download links for all where Title contains “Windows Embedded 8 Standard for x64”
Hi John! One can certainly search Microsoft Update Catalog for that string, but the hardest part is pagination – I do not know how to programmatically move between pages there nor I know how to get the search results in one list w/o pagination.