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 " - $_" } }
}
}

View File

@@ -0,0 +1,40 @@
# WSUS Display Top Error Computers (PowerShell)
Find the **top N computers** with the most Windows Update failures in the last **N days** from WSUS, list their failed updates, and export results to CSV.
## What the script does
- Reads WSUS **event history** over a time window.
- Aggregates errors **per computer** and shows the **Top N**.
- Prints failed **KB titles per machine**.
- Exports a CSV: `WSUS_FailedComputers_YYYYMMDD.csv`.
## Requirements
- Run **on the WSUS server**, in an **elevated** 64-bit PowerShell.
- WSUS API available:
- `UpdateServices` module **or**
- `"%ProgramFiles%\Update Services\Tools\Microsoft.UpdateServices.Administration.dll"`.
## Usage
Save as `Top-ErrorComputers.ps1`, then run:
```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\Top-ErrorComputers.ps1
```
## Configuration
Edit the variables at the top of the script:
- `$Days` time window (default: `7`)
- `$Top` number of computers to display (default: `10`)
- `$OutCsv` export path
## Output
- Console table: `ComputerName`, `IPAddress`, `Errors`, `LastError`
- CSV file at `$OutCsv`
- For each “top” computer, a list of **failed update titles** is printed below the table.
## Optional: schedule (Task Scheduler)
```powershell
schtasks /Create /TN "WSUS Top Error Computers" ^
/TR "powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\Scripts\Top-ErrorComputers.ps1" ^
/SC DAILY /ST 02:00 /RU SYSTEM /RL HIGHEST /F
```