Public/Get-LatestUpdate.ps1
Function Get-LatestUpdate { <# .SYNOPSIS Get the latest Cumulative update for Windows .DESCRIPTION This script will return the list of Cumulative updates for Windows 10 and Windows Server 2016 from the Microsoft Update Catalog. Optionally download the updates using the -Download parameter. .NOTES Author: Aaron Parker Twitter: @stealthpuppy Original script: Copyright Keith Garner, All rights reserved. Forked from: https://gist.github.com/keithga/1ad0abd1f7ba6e2f8aff63d94ab03048 .LINK https://support.microsoft.com/en-us/help/4043454 .PARAMETER Build Specify the Windows build number for searching cumulative updates. Supports '16299', '15063', '14393', '10586', '10240'. .PARAMETER SearchString Specify a specific search string to change the target update behaviour. The default will only download Cumulative updates for x64. .EXAMPLE Get-LatestUpdate Description: Get the latest Cumulative Update for Windows 10 x64 .EXAMPLE Get-LatestUpdate -SearchString 'Cumulative.*x86' Description: Enumerate the latest Cumulative Update for Windows 10 x86 (Semi-Annual Channel) .EXAMPLE Get-LatestUpdate -SearchString 'Cumulative.*Server.*x64' -Build 14393 Description: Enumerate the latest Cumulative Update for Windows Server 2016 #> [CmdletBinding(SupportsShouldProcess = $False)] Param( [Parameter(Mandatory = $False, HelpMessage = "JSON source for the update KB articles.")] [Parameter(ParameterSetName = 'Download', Mandatory = $False)] [string]$StartKB = 'https://support.microsoft.com/app/content/api/content/asset/en-us/4000816', [Parameter(Mandatory = $False, HelpMessage = "Windows build number.")] [ValidateSet('16299', '15063', '14393', '10586', '10240')] [string]$Build = '16299', [Parameter(Mandatory = $False, HelpMessage = "Search query string.")] [string]$SearchString = 'Cumulative.*x64' ) Begin { } Process { #region Find the KB Article Number Write-Verbose "Downloading $StartKB to retrieve the list of updates." $kbID = (Invoke-WebRequest -Uri $StartKB).Content | ConvertFrom-Json | Select-Object -ExpandProperty Links | Where-Object level -eq 2 | Where-Object text -match $Build | Select-LatestUpdate | Select-Object -First 1 #endregion #region get the download link from Windows Update $Kb = $kbID.articleID Write-Verbose "Found ID: KB$($kbID.articleID)" $kbObj = Invoke-WebRequest -Uri "http://www.catalog.update.microsoft.com/Search.aspx?q=KB$($kbID.articleID)" $Available_kbIDs = $kbObj.InputFields | Where-Object { $_.Type -eq 'Button' -and $_.Value -eq 'Download' } | Select-Object -ExpandProperty ID $Available_kbIDs | Out-String | Write-Verbose $kbIDs = $kbObj.Links | Where-Object ID -match '_link' | Where-Object innerText -match $SearchString | ForEach-Object { $_.Id.Replace('_link', '') } | Where-Object { $_ -in $Available_kbIDs } # If innerHTML is empty or does not exist, use outerHTML instead If ( $Null -eq $kbIDs ) { $kbIDs = $kbObj.Links | Where-Object ID -match '_link' | Where-Object outerHTML -match $SearchString | ForEach-Object { $_.Id.Replace('_link', '') } | Where-Object { $_ -in $Available_kbIDs } } $Urls = @() ForEach ( $kbID in $kbIDs ) { Write-Verbose "`t`tDownload $kbID" $Post = @{ size = 0; updateID = $kbID; uidInfo = $kbID } | ConvertTo-Json -Compress $PostBody = @{ updateIDs = "[$Post]" } $Urls += Invoke-WebRequest -Uri 'http://www.catalog.update.microsoft.com/DownloadDialog.aspx' -Method Post -Body $postBody | Select-Object -ExpandProperty Content | Select-String -AllMatches -Pattern "(http[s]?\://download\.windowsupdate\.com\/[^\'\""]*)" | ForEach-Object { $_.matches.value } } #endregion } End { $Notes = $kbObj.ParsedHtml.body.getElementsByTagName('a') | ForEach-Object InnerText | Where-Object { $_ -match $SearchString } [int]$i = 0; $Output = @() ForEach ( $Url in $Urls ) { $item = New-Object PSObject $item | Add-Member -type NoteProperty -Name 'KB' -Value "KB$Kb" If ( $Notes.Count -eq 1 ) { $item | Add-Member -type NoteProperty -Name 'Note' -Value $Notes } Else { $item | Add-Member -type NoteProperty -Name 'Note' -Value $Notes[$i] } $item | Add-Member -type NoteProperty -Name 'URL' -Value $Url $Output += $item $i = $i + 1 } # Write the URLs list to the pipeline Write-Output $Output } } |