Dargslan.WinHotfixDelta.psm1
|
<# .SYNOPSIS Windows hotfix delta analysis toolkit — patch gap detection, superseded updates, rollback history, and servicing stack analysis .DESCRIPTION 2026 Edition — Dargslan Windows Admin Toolkit. https://dargslan.com | https://dargslan.com/cheat-sheets .LINK https://dargslan.com #> function Get-HotfixDeltaAnalysis { <# .SYNOPSIS Analyze hotfix gaps, superseded patches, and servicing .DESCRIPTION Part of Dargslan.WinHotfixDelta (2026 Edition) — https://dargslan.com #> [CmdletBinding()] param([switch]$Json) $report = [ordered]@{ AllHotfixes = Get-HotFix -ErrorAction SilentlyContinue | Sort-Object InstalledOn -Descending | Select-Object HotFixID, Description, InstalledOn, InstalledBy PatchGaps = @() ServicingStack = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing" -ErrorAction SilentlyContinue) PendingReboot = [PSCustomObject]@{ ComponentBased = Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending" WindowsUpdate = Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired" PendingRename = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -ErrorAction SilentlyContinue).PendingFileRenameOperations -ne $null } Summary = [PSCustomObject]@{ TotalHotfixes = 0; OldestPatch = ""; NewestPatch = ""; PatchSpanDays = 0; RebootPending = $false } } $hf = $report.AllHotfixes | Where-Object InstalledOn $report.Summary.TotalHotfixes = ($report.AllHotfixes | Measure-Object).Count if ($hf.Count -gt 0) { $oldest = ($hf | Sort-Object InstalledOn | Select-Object -First 1).InstalledOn $newest = ($hf | Sort-Object InstalledOn -Descending | Select-Object -First 1).InstalledOn $report.Summary.OldestPatch = $oldest.ToString("yyyy-MM-dd") $report.Summary.NewestPatch = $newest.ToString("yyyy-MM-dd") $report.Summary.PatchSpanDays = [math]::Round(($newest - $oldest).TotalDays, 0) $sorted = $hf | Sort-Object InstalledOn for ($i = 1; $i -lt [math]::Min($sorted.Count, 30); $i++) { $gap = ($sorted[$i].InstalledOn - $sorted[$i-1].InstalledOn).TotalDays if ($gap -gt 45) { $report.PatchGaps += [PSCustomObject]@{ From=$sorted[$i-1].InstalledOn.ToString("yyyy-MM-dd"); To=$sorted[$i].InstalledOn.ToString("yyyy-MM-dd"); DaysGap=[math]::Round($gap,0) } } } } $report.Summary.RebootPending = $report.PendingReboot.ComponentBased -or $report.PendingReboot.WindowsUpdate if ($Json) { return $report | ConvertTo-Json -Depth 3 } Write-Host "`n [Hotfix Delta Analysis - 2026]" -ForegroundColor Cyan $report.Summary | Format-List if ($report.PatchGaps) { Write-Host " Patch Gaps (>45 days):" -ForegroundColor Yellow; $report.PatchGaps | Format-Table -AutoSize } $report.PendingReboot | Format-List $report.AllHotfixes | Select-Object -First 10 | Format-Table -AutoSize return $report } Export-ModuleMember -Function * |