Public/Get-MSCatalogUpdate.ps1
function Get-MSCatalogUpdate { <# .SYNOPSIS Query catalog.update.micrsosoft.com for available updates. .DESCRIPTION TBC .PARAMETER Search Specify a string to search for. .PARAMETER AllPages By default this command returns the first page of results from catalog.update.micrsosoft.com, which is the latest 25 updates matching the search term. If you specify this switch the command will instead return all pages of results. This can result in a significant increase in the number of HTTP requests to the catalog.update.micrsosoft.com endpoint. .PARAMETER Architecture Specify the architecture to search for e.g. "64-Bit" or "32-Bit". .EXAMPLE Get-MSCatalogUpdate -Search "Office 2013" .EXAMPLE Get-MSCatalogUpdate -Search "Office 2013" -AllPages .EXAMPLE Get-MSCatalogUpdate -Search "Office 2013" -Architecture "64-Bit" #> [CmdLetBinding()] param ( [Parameter( Mandatory = $true, Position = 0 )] [String] $Search, [Parameter( Mandatory = $false, Position = 1 )] [Switch] $AllPages, [Parameter( Mandatory = $false, Position = 2 )] [ValidateSet("64-Bit", "32-Bit")] [String] $Architecture, [Parameter(DontShow)] [String] $Method = "Get", [Parameter(DontShow)] [String] $EventArgument, [Parameter(DontShow)] [String] $EventTarget, [Parameter(DontShow)] [String] $EventValidation, [Parameter(DontShow)] [String] $ViewState, [Parameter(DontShow)] [String] $ViewStateGenerator ) if ($Method -eq "Post") { $ReqBody = @{ "__EVENTARGUMENT" = $EventArgument "__EVENTTARGET" = $EventTarget "__EVENTVALIDATION" = $EventValidation "__VIEWSTATE" = $ViewState "__VIEWSTATEGENERATOR" = $ViewStateGenerator } } $UriSearch = [Uri]::EscapeUriString($Search) $Params = @{ Uri = "https://www.catalog.update.microsoft.com/Search.aspx?q=$UriSearch" Method = $Method Body = $ReqBody ContentType = "application/x-www-form-urlencoded" UseBasicParsing = $true } $Results = Invoke-WebRequest @Params $HtmlDoc = [HtmlAgilityPack.HtmlDocument]::new() $HtmlDoc.LoadHtml($Results.RawContent.ToString()) $NextPage = $HtmlDoc.GetElementbyId("ctl00_catalogBody_nextPage") $EventArgument = $HtmlDoc.GetElementbyId("__EVENTARGUMENT")[0].Attributes["value"].Value $EventValidation = $HtmlDoc.GetElementbyId("__EVENTVALIDATION")[0].Attributes["value"].Value $ViewState = $HtmlDoc.GetElementbyId("__VIEWSTATE")[0].Attributes["value"].Value $ViewStateGenerator = $HtmlDoc.GetElementbyId("__VIEWSTATEGENERATOR")[0].Attributes["value"].Value $Table = $HtmlDoc.GetElementbyId("ctl00_catalogBody_updateMatches") $Rows = $Table.SelectNodes("tr") foreach ($Row in $Rows[1..($Rows.Count - 1)]) { $Cells = $Row.SelectNodes("td") if ($Architecture) { if ($Cells[1].innerText.Trim() -match $Architecture) { [PSCustomObject] @{ PSTypeName = "MSCatalogUpdate" Title = $Cells[1].innerText.Trim() Products = $Cells[2].innerText.Trim() Classification = $Cells[3].innerText.Trim() LastUpdated = ([DateTime] $Cells[4].innerText.Trim()).ToString("yyyy/MM/dd") Version = $Cells[5].innerText.Trim() Size = $Cells[6].SelectNodes("span")[0].InnerText SizeInBytes = [Int] $Cells[6].SelectNodes("span")[1].InnerText Guid = $Cells[7].SelectNodes("input")[0].Id } } } else { [PSCustomObject] @{ PSTypeName = "MSCatalogUpdate" Title = $Cells[1].innerText.Trim() Products = $Cells[2].innerText.Trim() Classification = $Cells[3].innerText.Trim() LastUpdated = ([DateTime] $Cells[4].innerText.Trim()).ToString("yyyy/MM/dd") Version = $Cells[5].innerText.Trim() Size = $Cells[6].SelectNodes("span")[0].InnerText SizeInBytes = [Int] $Cells[6].SelectNodes("span")[1].InnerText Guid = $Cells[7].SelectNodes("input")[0].Id } } } # If $NextPage is $null then there are more pages to collect. if (!$NextPage) { $NextParams = @{ Search = $Search EventArgument = $EventArgument EventTarget = 'ctl00$catalogBody$nextPageLinkText' EventValidation = $EventValidation ViewState = $ViewState ViewStateGenerator = $ViewStateGenerator Method = "Post" } if ($Architecture) { $NextParams.Architecture = $Architecture } if ($AllPages) { $NextParams.AllPages = $true Get-MSCatalogUpdate @NextParams } } } |