Resolve Windows Update Error Codes with PowerShell

I needed a way to resolve Windows Update error codes for a solution I am working on and I remembered there are a couple of web pages on the Microsoft Docs site that document Windows Update error codes, eg this and this.

So I decided to create a PowerShell function that scrapes these pages and pulls all the error codes and descriptions into a table. This allows me to dynamically resolves a particular error code to a friendly description, or simply output the entire table as a reference.

You can use the function like so:

Resolve a single error code
Get-WUErrorCode -ErrorCode 0x800f0825
# or
"0x800f0825" | Get-WUErrorCode
Resolve multiple error codes:
Get-WUErrorCode "0x8024A000","0x8024D00B"
# or
"0x8024A000","0x8024D00B" | Get-WUErrorCode  
Output the entire list of error codes and send to GridView:
Get-WUErrorCode -AsTable | Out-GridView

Here’s the code:

Function Get-WUErrorCode {
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true,ParameterSetName='Parameter Set 1',ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Position=0)]
[string[]]
$ErrorCode,
[Parameter(Mandatory=$true,ParameterSetName='Parameter Set 2',Position=1)]
[switch]
$AsTable
)
Begin
{
# create a table
$ErrorCodeTable = [System.Data.DataTable]::new()
$ErrorCodeTable.Columns.AddRange(@("ErrorCode","Description","Message","Category"))
################################
## PROCESS THE FIRST WEB PAGE ##
################################
# scrape the web page
$ProgressPreference = 'SilentlyContinue'
$URL = "https://docs.microsoft.com/en-us/windows/deployment/update/windows-update-error-reference"
$tempFile = [System.IO.Path]::GetTempFileName()
Invoke-WebRequest URI $URL OutFile $tempFile UseBasicParsing
$htmlarray = Get-Content $tempFile ReadCount 0
[System.IO.File]::Delete($tempFile)
# get the headers and data cells
$headers = $htmlarray | Select-String SimpleMatch "<h2 " | Where {$_ -notmatch "Feedback"}
$dataCells = $htmlarray | Select-String SimpleMatch "<td>"
# process each header
$i = 1
do {
foreach ($header in $headers)
{
$lineNumber = $header.LineNumber
$nextHeader = $headers[$i]
If ($null -ne $nextHeader)
{
$nextHeaderLineNumber = $nextHeader.LineNumber
$cells = $dataCells | Where {$_.LineNumber -gt $lineNumber -and $_.LineNumber -lt $nextHeaderLineNumber}
}
else
{
$cells = $dataCells | Where {$_.LineNumber -gt $lineNumber}
}
# process each cell
$totalCells = $cells.Count
$t = 0
do {
$Row = $ErrorCodeTable.NewRow()
"ErrorCode","Message","Description" | foreach {
$Row["$_"] = "$($cells[$t].ToString().Replace('<code>','').Replace('</code>','').Split('>').Split('<')[2])"
$t ++
}
$Row["Category"] = "$($header.ToString().Split('>').Split('<')[2])"
[void]$ErrorCodeTable.Rows.Add($Row)
}
until ($t -ge ($totalCells -1))
$i ++
}
}
until ($i -ge $headers.count)
#################################
## PROCESS THE SECOND WEB PAGE ##
#################################
# scrape the web page
$URL = "https://docs.microsoft.com/en-us/windows/deployment/update/windows-update-errors"
$tempFile = [System.IO.Path]::GetTempFileName()
Invoke-WebRequest URI $URL OutFile $tempFile UseBasicParsing
$htmlarray = Get-Content $tempFile ReadCount 0
[System.IO.File]::Delete($tempFile)
# get the headers and data cells
$headers = $htmlarray | Select-String SimpleMatch "<h2 " | Where {$_ -notmatch "Feedback"}
$dataCells = $htmlarray | Select-String SimpleMatch "<td>"
# process each header
$i = 1
do {
foreach ($header in $headers)
{
$lineNumber = $header.LineNumber
$nextHeader = $headers[$i]
If ($null -ne $nextHeader)
{
$nextHeaderLineNumber = $nextHeader.LineNumber
$cells = $dataCells | Where {$_.LineNumber -gt $lineNumber -and $_.LineNumber -lt $nextHeaderLineNumber}
}
else
{
$cells = $dataCells | Where {$_.LineNumber -gt $lineNumber}
}
# process each cell
$totalCells = $cells.Count
$t = 0
do {
$WebErrorCode = $header.ToString().Split('>').Split('<')[2].Replace('or ','').Replace(' ',' ').Split()
If ($WebErrorCode.GetType().BaseType.Name -eq "Array")
{
foreach ($Code in $WebErrorCode)
{
$Row = $ErrorCodeTable.NewRow()
$Row["ErrorCode"] = $Code.Trim()
"Message","Description" | foreach {
$Row["$_"] = "$($cells[$t].ToString().Split('>').Split('<')[2])"
$t ++
}
$Row["Category"] = "Common"
[void]$ErrorCodeTable.Rows.Add($Row)
1..2 | foreach {$t }
}
1..2 | foreach {$t ++}
}
else {
$Row = $ErrorCodeTable.NewRow()
$Row["ErrorCode"] = $ErrorCode
"Message","Description" | foreach {
$Row["$_"] = "$($cells[$t].ToString().Split('>').Split('<')[2])"
$t ++
}
$Row["Category"] = "Common"
[void]$ErrorCodeTable.Rows.Add($Row)
}
$t ++
}
until ($t -ge ($totalCells -1))
$i ++
}
}
until ($i -ge $headers.count)
$outputArray = @()
}
Process
{
if ($ErrorCode)
{
$ErrorCode | foreach {
$outputArray += ($ErrorCodeTable.Select("ErrorCode='$_'") | Select First 1)
}
}
}
End
{
if ($ErrorCode)
{
return $outputArray
}
if ($AsTable)
{
return $ErrorCodeTable
}
}
}