diff --git a/Utility Scripts/List installed Windows Updates.ps1 b/Utility Scripts/List installed Windows Updates.ps1 new file mode 100644 index 0000000..7dca94f --- /dev/null +++ b/Utility Scripts/List installed Windows Updates.ps1 @@ -0,0 +1,110 @@ +function Convert-WuaResultCodeToName { + param( + [Parameter(Mandatory = $true)] + [int] $ResultCode + ) + + switch ($ResultCode) { + 2 { "Succeeded" } + 3 { "Succeeded With Errors" } + 4 { "Failed" } + default { "Unknown ($ResultCode)" } + } +} + +function Get-WuaHistory { + $session = New-Object -ComObject 'Microsoft.Update.Session' + $searcher = $session.CreateUpdateSearcher() + + $historyCount = $searcher.GetTotalHistoryCount() + $history = $searcher.QueryHistory(0, $historyCount) + + $history | ForEach-Object { + $resultName = Convert-WuaResultCodeToName -ResultCode $_.ResultCode + + $product = $_.Categories | + Where-Object { $_.Type -eq 'Product' } | + Select-Object -First 1 -ExpandProperty Name + + $kb = if ($_.Title -match 'KB\d{7}') { $matches[0] } else { $null } + + [PSCustomObject]@{ + Source = 'WUA-History' + Result = $resultName + Date = $_.Date + KB = $kb + Title = $_.Title + Product = $product + } + } | + Where-Object { -not [string]::IsNullOrWhiteSpace($_.Title) } +} + +function Get-InstalledHotFixes { + Get-HotFix | ForEach-Object { + [PSCustomObject]@{ + Source = 'HotFix' + Result = 'Installed' + Date = $_.InstalledOn + KB = $_.HotFixID + Title = $_.Description + Product = 'Windows' + } + } +} + +function Get-DismPackages { + # Preferred path: Get-WindowsPackage (cleaner PowerShell objects) + if (Get-Command Get-WindowsPackage -ErrorAction SilentlyContinue) { + Get-WindowsPackage -Online | ForEach-Object { + $packageName = $_.PackageName + $kb = if ($packageName -match 'KB\d{7}') { $matches[0] } else { $null } + + [PSCustomObject]@{ + Source = 'DISM' + Result = 'Installed Package' + Date = $_.InstallTime + KB = $kb + Title = $packageName + Product = 'CBS Package' + } + } + } + else { + # Fallback: parse DISM text output + $raw = dism /online /get-packages /format:table 2>$null + + $raw | ForEach-Object { + $line = $_.Trim() + + # Skip blank/header/noise lines + if (-not $line) { return } + if ($line -match '^(Package Identity|State|Release Type|Install Time)') { return } + if ($line -match '^-{3,}$') { return } + + $kb = if ($line -match 'KB\d{7}') { $matches[0] } else { $null } + + [PSCustomObject]@{ + Source = 'DISM' + Result = 'Installed Package' + Date = $null + KB = $kb + Title = $line + Product = 'CBS Package' + } + } + } +} + +function Get-AllUpdates { + $wua = Get-WuaHistory + $hotfix = Get-InstalledHotFixes + $dism = Get-DismPackages + + ($wua + $hotfix + $dism) | + Where-Object { $_.KB -or $_.Title } | + Sort-Object Date -Descending +} + +# Full combined view +Get-AllUpdates | Format-Table -AutoSize \ No newline at end of file