Windows – Get all installed patches, updates and hotfixes
In this blog I will share one way to get all installed patches, updates and hotfixes on a local or a remote Windows workstation or server.
Introduction
There are multiple ways to check for installed patches, updates and hotfixes on a Windows systems. Most of these commands don’t list all installed patches and updates. Examples of these commands are:
- Get-HotFix Gets the hotfixes that are installed on local or remote computers.
- wmic qfe list
- Get-WmiObject -Class win32_quickfixengineering WMI class represents a small system-wide update, commonly referred to as a quick-fix engineering (QFE) update, applied to the current operating system.
In this blog I will share one way to get all installed patches, updates and hotfixes on a local or a remote Windows workstation or server.
PowerShell Cmdlets and Commands
- New-Object Creates an instance of a Microsoft .NET Framework or COM object. This will be used to connect to ‘Microsoft.Update.Session’.
- QueryHistory([in] BSTR criteria, [in] LONG startIndex, [in] LONG count) Synchronously queries the computer for the history of the update events.
- Add-Member Adds custom properties and methods to an instance of a PowerShell object.
- Invoke-Command Runs commands on local and remote computers.
Installed Patches and Updates on Local Computer
Note the addition of Product, Result, RevisionNumber and UpdateId properties.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$Session = (New-Object -ComObject 'Microsoft.Update.Session') # Query the latest 1000 events starting with the first record $History = $Session.QueryHistory("", 0, 1000) $Updates = ForEach ($Update in $History) { # Get and add update product name $Product = $Update.Categories | Where-Object {$_.Type -eq 'Product'} | Select-Object -First 1 -ExpandProperty Name $Update | Add-Member -MemberType NoteProperty -Value $Product -Name Product -PassThru # Get and add update result $Result = Switch ($Update.ResultCode) { 1 {"Installation"}; 2 {"Succeeded"}; 3 {"Succeeded With Errors"}; 4 {"Failed"} } $Update | Add-Member -MemberType NoteProperty -Value $Result -Name Result # Add update revision number $Update | Add-Member -MemberType NoteProperty -Value $Update.UpdateIdentity.RevisionNumber -Name RevisionNumber # Add update Id $Update | Add-Member -MemberType NoteProperty -Value $_UpdateUpdateIdentity.UpdateId -Name UpdateId } # Remove null records $Updates | Where-Object {![String]::IsNullOrWhiteSpace($_.title)} |
Below is a script output sample.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
PS C:\> $Updates[0] Categories : System.__ComObject ClientApplicationID : wusa Date : 10/26/2022 2:14:38 AM Description : Fix for KB5020439 HResult : 0 Operation : 1 Product : Windows Result : Uninstallation ResultCode : 2 RevisionNumber : 501 ServerSelection : 3 ServiceID : dce84aca-6959-4a5d-8640-b136f7fe3d90 SupportUrl : http://support.microsoft.com Title : Update for Windows (KB5020439) UninstallationNotes : This software update can be removed by selecting View installed updates in the Programs and Features Control Panel. UninstallationSteps : System.__ComObject UnmappedResultCode : 0 UpdateId : UpdateIdentity : System.__ComObject |
Installed Patches and Updates on Remote Computer
We will first encapsulate the above code in a function then use Invoke-Command to run the function on a remote computer. Note, we control the number of events returned by using a function variable with a default value of 1000 events.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
Function Get-WuaHistory { Param ( [int] $NoOfEvents = 1000 # Number of events to retrieve ) # Get a WUA Session $Session = (New-Object -ComObject 'Microsoft.Update.Session') # Query the latest $NoOfEvents History starting with the first recordp $History = $Session.QueryHistory("", 0, $NoOfEvents) $Updates = ForEach ($Update in $History) { # Get and add update product name $Product = $Update.Categories | Where-Object {$_.Type -eq 'Product'} | Select-Object -First 1 -ExpandProperty Name $Update | Add-Member -MemberType NoteProperty -Value $Product -Name Product -PassThru # Get and add update result $Result = Switch ($Update.ResultCode) { 1 {"Installation"}; 2 {"Succeeded"}; 3 {"Succeeded With Errors"}; 4 {"Failed"} } $Update | Add-Member -MemberType NoteProperty -Value $Result -Name Result # Add update revision number $Update | Add-Member -MemberType NoteProperty -Value $Update.UpdateIdentity.RevisionNumber -Name RevisionNumber # Add update Id $Update | Add-Member -MemberType NoteProperty -Value $_UpdateUpdateIdentity.UpdateId -Name UpdateId } # Remove null records $Updates | Where-Object {![String]::IsNullOrWhiteSpace($_.title)} } # To get installed patches and updates on a the local computer. ## $WuaHistory = Invoke-Command -ScriptBlock ${Function:Get-WuaHistory} -ErrorAction SilentlyContinue # To get installed patches and updates on a Windows computer. $WuaHistory = Invoke-Command -ComputerName "DEV-Server-01" -ScriptBlock ${Function:Get-WuaHistory} -ErrorAction SilentlyContinue # Display output $WuaHistory | Select Title, Result, Date |
Below is a script output sample.
1 2 3 4 5 6 7 |
Title Result Date ----- ------ ---- Update for Windows (KB5020439) Succeeded 10/26/2022 2:14:38 AM Windows Malicious Software Removal Tool x64 - v5.98 (KB890830) Succeeded 5/29/2022 10:42:46 PM Update for Windows (KB5015019) Succeeded 5/29/2022 10:01:43 PM 2022-02 Cumulative Update for Windows Server 2016 for x64-based Systems (KB5010359) Failed 2/27/2022 5:27:14 PM 2021-11 Cumulative Update for Windows Server 2016 for x64-based Systems (KB5007192) Succeeded 12/5/2021 5:39:49 PM |
Conclusion
Did you find this blog easy to follow and helpful to you? Let me know in the comments below.
Disclaimer
Purpose of the code contained in blog is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.
There's no comments