Skip to content

Instantly share code, notes, and snippets.

@PanosGreg
Last active March 26, 2024 14:46
Show Gist options
  • Save PanosGreg/6f53bcb821115abebec8031ba3135219 to your computer and use it in GitHub Desktop.
Save PanosGreg/6f53bcb821115abebec8031ba3135219 to your computer and use it in GitHub Desktop.
Get a list of the windows updates with a KB ID using the COM Microsoft.Update.Searcher
function Get-WinUpdate {
<#
.SYNOPSIS
Get a list of all the windows updates on the system
Note: This function will only show the updates that have a KB ID
Any hotfixes without an update ID won't be included in the results
.EXAMPLE
Get-WinUpdate | where Title -like '*cumulative update for windows*'
.EXAMPLE
Get-WinUpdate -UpdateID KB503*
# you can filter based on the KB ID, which can take a wildcard if you want
.EXAMPLE
Get-WinUpdate | Where-Object Title -like '*Cumulative Update for Windows*' | Select-Object -First 1
# get the latest Windows Cumulative Update that's installed on the system
#>
[OutputType([pscustomobject])]
[cmdletbinding()]
param (
[string]$UpdateID = '*'
)
if (-not '_DateComparer' -as [type]) {
class _DateComparer : System.Collections.Generic.IComparer[PSObject] {
# Properties
[string]$PropertyName
[bool]$Descending = $false
# Constructors
_DateComparer([string]$Property) {
$this.PropertyName = $Property
}
_DateComparer([string]$Property,[bool]$Descending) {
$this.PropertyName = $Property
$this.Descending = $Descending
}
# Compare method
[int] Compare ([PSObject]$a,
[PSObject]$b) {
$ValueA = $a.$($this.PropertyName)
$ValueB = $b.$($this.PropertyName)
if ($ValueA -eq $ValueB) {$result = 0}
elseif ($ValueA -lt $ValueB) {$result = -1}
else {$result = 1}
if($this.Descending) {$result *= -1}
return $result
}
} #class
} #if class
$Compare = [_DateComparer]::new('InstallDate',$true)
$SortedSet = [System.Collections.Generic.SortedSet[psobject]]::new($Compare)
$TempList = [System.Collections.Generic.List[string]]::new()
$Search = New-Object -ComObject 'Microsoft.Update.Searcher'
$Count = $Search.GetTotalHistoryCount()
$Search.QueryHistory(0, $Count) | ForEach {
$ParseKB = [regex]::Match($_.Title,'(KB\d{6,8})')
if ($ParseKB.Success) {
$ParseDate = [regex]::Match($_.Title,'^(\d{4})-(\d{2})\s')
if ($ParseDate.Success) {
$PatchMonth = $ParseDate.Groups[2].Value -as [int]
$PatchYear = $ParseDate.Groups[1].Value -as [int]
}
else {$PatchMonth = $null ; $PatchYear = $null}
$KB = $ParseKB.Groups[1].Value
$obj = [pscustomobject] @{
PSTypeName = 'Hotfix.WithTitle'
ComputerName = $env:COMPUTERNAME.ToUpper()
KB = $KB
InstallDate = $_.Date
Title = $_.Title
PatchMonth = $PatchMonth
PatchYear = $PatchYear
}
if (-not $TempList.Contains($KB)) {
$TempList.Add($KB)
[void]$SortedSet.Add($obj)
}
}
}
$prop = [string[]]('ComputerName','KB','InstallDate','Title')
$ddps = 'DefaultDisplayPropertySet'
$pset = [Management.Automation.PSPropertySet]::new($ddps,$prop)
$Memb = [Management.Automation.PSMemberInfo[]]@($pset)
$TempList.Clear()
$SortedSet.Where({$_.KB -like $UpdateID}) |
Add-Member -Member MemberSet -Name PSStandardMembers -Value $Memb -Pass
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment