From 679f0c71fecdb2cd353950443bfcb62408e0c993 Mon Sep 17 00:00:00 2001 From: Martien Date: Wed, 8 Jul 2026 14:14:07 +0200 Subject: [PATCH] feat: add manual download KB updates script --- SCCM-WU/ManualDownloadPatches.ps1 | 112 ++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 SCCM-WU/ManualDownloadPatches.ps1 diff --git a/SCCM-WU/ManualDownloadPatches.ps1 b/SCCM-WU/ManualDownloadPatches.ps1 new file mode 100644 index 0000000..ab79c1a --- /dev/null +++ b/SCCM-WU/ManualDownloadPatches.ps1 @@ -0,0 +1,112 @@ +$ErrorActionPreference = 'Stop' + +$outDir = 'C:\install\missing_updates' +if (-not (Test-Path $outDir)) { + New-Item -Path $outDir -ItemType Directory -Force | Out-Null +} +$logFile = Join-Path $outDir 'missing_updates.txt' +if (Test-Path $logFile) { Remove-Item $logFile -Force } + +function Log { + param([string]$Text) + Write-Host $Text + Add-Content -Path $logFile -Value $Text +} + +Log "Online WU scan (buiten WSUS om) - $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" +Log "Server: $env:COMPUTERNAME" +Log ('=' * 70) + +# --- Online scan tegen Microsoft Update, WSUS negeren --- +Log "" +Log "Scannen tegen Microsoft Update (kan een paar minuten duren)..." +$session = New-Object -ComObject Microsoft.Update.Session +$searcher = $session.CreateUpdateSearcher() +$searcher.ServerSelection = 3 # ssOthers = expliciet niet WSUS +$searcher.ServiceID = '7971f918-a847-4430-9279-4a52d1efe18d' # Microsoft Update + +$result = $searcher.Search("IsInstalled=0 AND Type='Software' AND IsHidden=0") + +$count = $result.Updates.Count +Log "Aantal ontbrekende updates gevonden: $count" +Log ('=' * 70) + +if ($count -eq 0) { + Log "" + Log "Geen ontbrekende updates. Server is up-to-date volgens Microsoft Update." + return +} + +# --- Per update: details loggen en download-URL's verzamelen --- +$downloadList = @() + +for ($i = 0; $i -lt $count; $i++) { + $u = $result.Updates.Item($i) + $kb = ($u.KBArticleIDs | ForEach-Object { "KB$_" }) -join ', ' + + Log "" + Log ("-" * 70) + Log "[$($i+1)/$count] $($u.Title)" + Log " KB: $kb" + Log " Ernst: $($u.MsrcSeverity)" + Log " UpdateID: $($u.Identity.UpdateID)" + + # Download-URL's uit de bundle halen (bundelt vaak de echte .msu) + $bundled = $u.BundledUpdates + if ($bundled.Count -eq 0) { + # Geen bundle, probeer update zelf + foreach ($c in $u.DownloadContents) { + if ($c.DownloadUrl) { + Log " URL: $($c.DownloadUrl)" + $downloadList += [PSCustomObject]@{ KB = $kb; Url = $c.DownloadUrl } + } + } + } else { + for ($b = 0; $b -lt $bundled.Count; $b++) { + $bu = $bundled.Item($b) + foreach ($c in $bu.DownloadContents) { + if ($c.DownloadUrl) { + Log " URL: $($c.DownloadUrl)" + $downloadList += [PSCustomObject]@{ KB = $kb; Url = $c.DownloadUrl } + } + } + } + } +} + +# --- Download-URL's apart wegschrijven --- +$urlFile = Join-Path $outDir 'download_urls.txt' +$downloadList | ForEach-Object { $_.Url } | Sort-Object -Unique | Set-Content $urlFile +Log "" +Log ('=' * 70) +Log "Alle download-URL's staan in: $urlFile" + +# --- Bestanden downloaden via BITS --- +Log "" +Log "Downloaden naar $outDir ..." +$n = 0 +foreach ($item in ($downloadList | Sort-Object Url -Unique)) { + $n++ + $fileName = Split-Path $item.Url -Leaf + # Zorg dat de bestandsnaam het KB-nummer bevat voor herkenbaarheid + $kbClean = ($item.KB -replace '[, ]', '_') + $dest = Join-Path $outDir "$($kbClean)__$fileName" + + Log " [$n] $fileName" + try { + Start-BitsTransfer -Source $item.Url -Destination $dest -ErrorAction Stop + $size = [math]::Round((Get-Item $dest).Length / 1MB, 1) + Log " OK ($size MB)" + } + catch { + Log " MISLUKT: $($_.Exception.Message)" + Log " Handmatig downloaden via bovenstaande URL." + } +} + +Log "" +Log ('=' * 70) +Log "Klaar: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" +Log "Rapport: $logFile" +Log "URL-lijst: $urlFile" +Log "Bestanden: $outDir" \ No newline at end of file