Auto-commit: 2025-10-31 08:55:43

This commit is contained in:
David Wuibaille
2025-10-31 08:55:43 +01:00
parent 9bb5ad24bb
commit 24c0c6509f
33 changed files with 13144 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
#Requires -RunAsAdministrator
$ErrorActionPreference = 'Stop'
# ---- Parameters ----
$Days = 7 # time window for error events
$Top = 10 # top N computers by error count
$OutCsv = "$PSScriptRoot\WSUS_FailedComputers_{0:yyyyMMdd}.csv" -f (Get-Date)
# ---- Connect to WSUS (module if available, else DLL) ----
if (Get-Module -ListAvailable UpdateServices) {
Import-Module UpdateServices -ErrorAction Stop
$wsus = Get-WsusServer
} else {
$dll = "$env:ProgramFiles\Update Services\Tools\Microsoft.UpdateServices.Administration.dll"
if (-not (Test-Path $dll)) { throw "WSUS Admin DLL not found: $dll" }
Add-Type -Path $dll
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer()
}
# ---- Pull error events in the time window ----
$from = (Get-Date).Date.AddDays(-[int]$Days)
$to = (Get-Date).Date
$events = $wsus.GetUpdateEventHistory($from, $to) |
Where-Object { $_.IsError -and $_.ComputerId -ne [Guid]::Empty }
# ---- Aggregate per computer and take Top N ----
$allComputers = $wsus.GetComputerTargets()
$compById = @{}; foreach ($c in $allComputers) { $compById[$c.Id] = $c }
$topByCount = $events | Group-Object ComputerId |
Sort-Object Count -Descending | Select-Object -First $Top
$result = foreach ($g in $topByCount) {
$c = $compById[$g.Name]
$lastEvt = $events | Where-Object { $_.ComputerId -eq $c.Id } |
Sort-Object CreationDate -Descending | Select-Object -First 1
[pscustomobject]@{
ComputerName = $c.FullDomainName
IPAddress = $c.IPAddress
Errors = $g.Count
LastError = $lastEvt.CreationDate
}
}
# ---- Output: table + CSV ----
$result | Format-Table -AutoSize
$result | Export-Csv -Path $OutCsv -NoTypeInformation -Encoding UTF8
Write-Host "CSV: $OutCsv"
# ---- For each top computer, list failed updates (titles) ----
$updScope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
foreach ($item in $result) {
$pc = $allComputers | Where-Object { $_.FullDomainName -eq $item.ComputerName }
if (-not $pc) { continue }
$failed = $pc.GetUpdateInstallationInfoPerUpdate($updScope) |
Where-Object UpdateInstallationState -EQ 'Failed'
if ($failed) {
Write-Host "`n$($item.ComputerName) — failed updates:"
foreach ($u in $failed) { ($wsus.GetUpdate($u.UpdateId).Title) | ForEach-Object { Write-Host " - $_" } }
}
}