Skip to content

Instantly share code, notes, and snippets.

@jborean93
Last active March 30, 2023 16:09
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jborean93/166f30af61e74ff1640662dfa4bccce6 to your computer and use it in GitHub Desktop.
Save jborean93/166f30af61e74ff1640662dfa4bccce6 to your computer and use it in GitHub Desktop.
Output a list of updates based on the criteria that you define
# Copyright: (c) 2020, Jordan Borean (@jborean93) <jborean93@gmail.com>
# MIT License (see LICENSE or https://opensource.org/licenses/MIT)
Function Write-WUAError {
<#
.SYNOPSIS
Convert raw HRESULT codes to a human readable error.
.PARAMETER Exception
The COMException that the error code is from.
.PARAMETER Context
Further context to add to the error message.
.NOTES
Error codes are from https://docs.microsoft.com/en-us/previous-versions/windows/desktop/hh968413(v=vs.85).
#>
[CmdletBinding()]
param (
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[System.Runtime.InteropServices.COMException]
$Exception,
[String]
$Context
)
$constant, $description = switch ($Exception.ErrorCode) {
0x00240001 { 'WU_S_SERVICE_STOP', 'WUA was stopped successfully.' }
0x00240002 { 'WU_S_SELFUPDATE', 'WUA updated itself.' }
0x00240003 { 'WU_S_UPDATE_ERROR', 'The operation completed successfully but errors occurred applying the updates.' }
0x00240004 { 'WU_S_MARKED_FOR_DISCONNECT', 'A callback was marked to be disconnected later because the request to disconnect the operation came while a callback was executing.' }
0x00240005 { 'WU_S_REBOOT_REQUIRED', 'The system must be restarted to complete installation of the update.' }
0x00240006 { 'WU_S_ALREADY_INSTALLED', 'The update to be installed is already installed on the system.' }
0x00240007 { 'WU_S_ALREADY_UNINSTALLED', 'The update to be removed is not installed on t he system.' }
0x00240008 { 'WU_S_ALREADY_DOWNLOADED', 'The update to be downloaded has already been downloaded.' }
0x00242015 { 'WU_S_UH_INSTALLSTILLPENDING', 'The installation operation for the update is still in progress.' }
0x80240001 { 'WU_E_NO_SERVICE', 'WUA was unable to provide the service.' }
0x80240002 { 'WU_E_MAX_CAPACITY_REACHED', 'The maximum capacity of the service was exceeded.' }
0x80240003 { 'WU_E_UNKNOWN_ID', 'WUA cannot find an ID.' }
0x80240004 { 'WU_E_NOT_INITIALIZED', 'The object could not be initialized.' }
0x80240005 { 'WU_E_RANGEOVERLAP', 'The update handler requested a byte range overlapping a previously requested range.' }
0x80240006 { 'WU_E_TOOMANYRANGES', 'The requested number of byte ranges exceeds the maximum number (2³¹ - 1).' }
0x80240007 { 'WU_E_INVALIDINDEX', 'The index to a collection was invalid.' }
0x80240008 { 'WU_E_ITEMNOTFOUND', 'The key for the item queried could not be found.' }
0x80240009 { 'WU_E_OPERATIONINPROGRESS', 'Another conflicting operation was in progress. Some operations such as installation cannot be performed twice simultaneously.' }
0x8024000A { 'WU_E_COULDNOTCANCEL', 'Cancellation of the operation was not allowed.' }
0x8024000B { 'WU_E_CALL_CANCELLED', 'Operation was cancelled.' }
0x8024000C { 'WU_E_NOOP', 'No operation was required.' }
0x8024000D { 'WU_E_XML_MISSINGDATA', 'WUA could not find required information in the update''s XML data.' }
0x8024000E { 'WU_E_XML_INVALID', 'WUA found invalid information in the update''s XML data.' }
0x8024000F { 'WU_E_CYCLE_DETECTED', 'Circular update relationships were detected in the metadata.' }
0x80240010 { 'WU_E_TOO_DEEP_RELATION', 'Update relationships too deep to evaluate were evaluated.' }
0x80240011 { 'WU_E_INVALID_RELATIONSHIP', 'An invalid update relationship was detected.' }
0x80240012 { 'WU_E_REG_VALUE_INVALID', 'An invalid registry value was read.' }
0x80240013 { 'WU_E_DUPLICATE_ITEM', 'Operation tried to add a duplicate item to a list.' }
0x80240014 { 'WU_E_INVALID_INSTALL_REQUESTED', 'Updates that are requested for install are not installable by the caller.' }
0x80240016 { 'WU_E_INSTALL_NOT_ALLOWED', 'Operation tried to install while another installation was in progress or the system was pending a mandatory restart.' }
0x80240017 { 'WU_E_NOT_APPLICABLE', 'Operation was not performed because there are no applicable updates.' }
0x80240018 { 'WU_E_NO_USERTOKEN', 'Operation failed because a required user token is missing.' }
0x80240019 { 'WU_E_EXCLUSIVE_INSTALL_CONFLICT', 'An exclusive update can''t be installed with other updates at the same time.' }
0x8024001A { 'WU_E_POLICY_NOT_SET', 'A policy value was not set.' }
0x8024001B { 'WU_E_SELFUPDATE_IN_PROGRESS', 'The operation could not be performed because the Windows Update Agent is self-updating.' }
0x8024001D { 'WU_E_INVALID_UPDATE', 'An update contains invalid metadata.' }
0x8024001E { 'WU_E_SERVICE_STOP', 'Operation did not complete because the service or system was being shut down.' }
0x8024001F { 'WU_E_NO_CONNECTION', 'Operation did not complete because the network connection was unavailable.' }
0x80240020 { 'WU_E_NO_INTERACTIVE_USER', 'Operation did not complete because there is no logged-on interactive user.' }
0x80240021 { 'WU_E_TIME_OUT', 'Operation did not complete because it timed out.' }
0x80240022 { 'WU_E_ALL_UPDATES_FAILED', 'Operation failed for all the updates.' }
0x80240023 { 'WU_E_EULAS_DECLINED', 'The license terms for all updates were declined.' }
0x80240024 { 'WU_E_NO_UPDATE', 'There are no updates.' }
0x80240025 { 'WU_E_USER_ACCESS_DISABLED', 'Group Policy settings prevented access to Windows Update.' }
0x80240026 { 'WU_E_INVALID_UPDATE_TYPE', 'The type of update is invalid.' }
0x80240027 { 'WU_E_URL_TOO_LONG', 'The URL exceeded the maximum length.' }
0x80240028 { 'WU_E_UNINSTALL_NOT_ALLOWED', 'The update could not be uninstalled because the request did not originate from a Windows Server Update Services (WSUS) server.' }
0x80240029 { 'WU_E_INVALID_PRODUCT_LICENSE', 'Search may have missed some updates before there is an unlicensed application on the system.' }
0x8024002A { 'WU_E_MISSING_HANDLER', 'A component required to detect applicable updates was missing.' }
0x8024002B { 'WU_E_LEGACYSERVER', 'An operation did not complete because it requires a newer version of server.' }
0x8024002C { 'WU_E_BIN_SOURCE_ABSENT', 'A delta-compressed update could not be installed because it required the source.' }
0x8024002D { 'WU_E_SOURCE_ABSENT', 'A full-file update could not be installed because it required the source.' }
0x8024002E { 'WU_E_WU_DISABLED', 'Access to an unmanaged server is not allowed.' }
0x8024002F { 'WU_E_CALL_CANCELLED_BY_POLICY', 'Operation did not complete because the DisableWindowsUpdateAccess policy was set in the registry.' }
0x80240030 { 'WU_E_INVALID_PROXY_SERVER', 'The format of the proxy list was invalid.' }
0x80240031 { 'WU_E_INVALID_FILE', 'The file is in the wrong format.' }
0x80240032 { 'WU_E_INVALID_CRITERIA', 'The search criteria string was invalid.' }
0x80240033 { 'WU_E_EULA_UNAVAILABLE', 'License terms could not be downloaded.' }
0x80240034 { 'WU_E_DOWNLOAD_FAILED', 'Update failed to download.' }
0x80240035 { 'WU_E_UPDATE_NOT_PROCESSED', 'The update was not processed.' }
0x80240036 { 'WU_E_INVALID_OPERATION', 'The object''s current state did not allow the operation.' }
0x80240037 { 'WU_E_NOT_SUPPORTED', 'The functionality for the operation is not supported.' }
0x80240039 { 'WU_E_TOO_MANY_RESYNC', 'Agent is asked by server to resync too many times.' }
0x80240040 { 'WU_E_NO_SERVER_CORE_SUPPORT', 'The WUA API method does not run on the server core installation.' }
0x80240041 { 'WU_E_SYSPREP_IN_PROGRESS', 'Service is not available while sysprep is running.' }
0x80240042 { 'WU_E_UNKNOWN_SERVICE', 'The update service is no longer registered with automatic updates.' }
0x80240043 { 'WU_E_NO_UI_SUPPORT', 'No support for the WUA user interface.' }
0x80240044 { 'WU_E_PER_MACHINE_UPDATE_ACCESS_DENIED', 'Only administrators can perform this operation on per-computer updates.' }
0x80240045 { 'WU_E_UNSUPPORTED_SEARCHSCOPE', 'A search was attempted with a scope that is not currently supported for this type of search.' }
0x80240046 { 'WU_E_BAD_FILE_URL', 'The URL does not point to a file.' }
0x80240047 { 'WU_E_NOTSUPPORTED', 'The operation requested is not supported.' }
0x80240048 { 'WU_E_INVALID_NOTIFICATION_INFO', 'The featured update notification info returned by the server is invalid.' }
0x80240049 { 'WU_E_OUTOFRANGE', 'The data is out of range.' }
0x8024004A { 'WU_E_SETUP_IN_PROGRESS', 'WUA operations are not available while operating system setup is running.' }
0x80240FFF { 'WU_E_UNEXPECTED', 'An operation failed due to reasons not covered by another error code.' }
default { 'UNKNOWN', "Unknown error code $($Exception.ErrorCode)." }
}
if (-not $Context) {
$Context = "Error received from WUA"
}
$errorParams = @{
Message = '{0} (0x{1:X8} {2}): {3}' -f ($Context, $Exception.ErrorCode, $constant, $description)
Exception = $Exception
}
Write-Error @errorParams
}
Function Get-WindowsUpdate {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[AllowEmptyString()]
[String]
$Filter,
[Switch]
$Online
)
$session = New-Object -ComObject Microsoft.Update.Session
try {
$searcher = $session.CreateUpdateSearcher()
} catch [System.Runtime.InteropServices.COMException] {
$_.Exception | Write-WUAError -Context "Creating update searcher"
return
}
$searcher.Online = $Online.IsPresent
#$searcher.ServerSelection = 0
#$searcher.ServiceId = '8b24b027-1dee-babb-9a95-3517dfb9c552' # DCat Flighting Prod
#$searcher.ServiceId = '855e8a7c-ecb4-4ca3-b045-1dfa50104289' # Windows Store (DCat Prod)
# $searcher.IncludePotentiallySupersededUpdates = $true
try {
$searchResult = $searcher.Search($Filter)
} catch [System.Runtime.InteropServices.COMException] {
$_.Exception | Write-WUAError -Context "Search with filter '$Filter'"
return
}
if ($searchResult.ResultCode -notin @(2, 3)) {
$errorTitle, $errorMsg = switch ($searchResult.ResultCode) {
0 { 'NotStarted', 'The operation is not started.' }
1 { 'InProgress', 'The operation is in progress.' }
2 { 'Succeeded', 'The operation was completed successfully.' }
3 { 'SucceededWithErrors', 'The operation is complete, but one or more errors occurred during the operation. The results might be incomplete.' }
4 { 'Failed', 'The operation failed to complete.' }
5 { 'Aborted', 'The operation is canceled.' }
default { 'Unknown', "Unknown result code $($searchResult.ResultCode)."}
}
Write-Error -Message "Search for updates failed with $errorTitle - $errorMsg"
return
}
foreach ($warning in $searchResult.Warnings) {
Write-Warning -Message '{0} - {1}' -f ($warning.Message, $warning.HResult)
}
foreach ($update in $searchResult.Updates) {
$installBehaviour = $update.InstallationBehavior
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-uamg/9ed3c4f7-30fc-4b7b-97e1-308b5159822c
$impact = switch ($installBehaviour.Impact) {
0 { 'Normal' }
1 { 'Minor' }
2 { 'RequiresExclusiveHandling' }
default { "Unknown $($installBehaviour.Impact)" }
}
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-uamg/eee24bbd-0be7-4a81-bed5-bff1fbb1832b
$rebootBehavior = switch ($installBehaviour.RebootBehavior) {
0 { 'NeverReboots' }
1 { 'AlwaysRequiresReboot' }
2 { 'CanRequestReboot' }
default { "Unknown $($installBehaviour.RebootBehavior)" }
}
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-uamg/a4ec1231-6523-4196-8497-7b63ecc35b61
$updateType = switch ($update.Type) {
1 { 'Software' }
2 { 'Driver' }
default { "Unknown $($update.Type)" }
}
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-uamg/d4dc5648-a8a9-436d-9fdd-c90730bf64b0
$deploymentAction = switch ($update.DeploymentAction) {
0 { 'None' }
1 { 'Installation' }
2 { 'Uninstallation' }
3 { 'Detection' }
default { "Unknown $($update.DeploymentAction)" }
}
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-uamg/012a7226-c23d-4905-b630-9a6506032aa9
$autoSelection = switch ($update.AutoSelection) {
0 { 'LetWindowsUpdateDecide' }
1 { 'AutoSelectIfDownloaded' }
2 { 'NeverAutoSelect' }
3 { 'AlwaysAutoSelect' }
default { "Unknown $($update.AutoSelection)" }
}
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-uamg/02e59b57-4d4e-4060-ab69-8207a10271aa
$autoDownload = switch ($update.AutoDownload) {
0 { 'LetWindowsUpdateDecide' }
1 { 'NeverAutoDownload' }
2 { 'AlwaysAutoDownload' }
default { "Unknown $($update.AutoDownload)" }
}
[PSCustomObject]@{
# User friendly info
Title = $update.Title
Description = $update.Description
KB = 'KB{0}' -f (@($update.KBArticleIDs | ForEach-Object { $_ })[0])
# Search filter critera
Type = $updateType
DeploymentAction = $deploymentAction
AutoSelectOnWebSites = $update.AutoSelectOnWebSites
BrowseOnly = $update.BrowseOnly
UpdateID = $update.Identity.UpdateID
RevisionNumber = $update.Identity.RevisionNumber
Categories = @($update.Categories | ForEach-Object { $_.Name })
IsInstalled = $update.IsInstalled
IsHidden = $update.IsHidden
IsPresent = $update.IsPresent
RebootRequired = $update.RebootRequired
# Extra info
Impact = $impact
RebootBehavior = $rebootBehavior
IsBeta = $update.IsBeta
IsDownloaded = $update.IsDownloaded
IsMandatory = $update.IsMandatory
IsUninstallable = $update.IsUninstallable
AutoSelection = $autoSelection
AutoDownload = $autoDownload
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment