Update SCCM-WU/Fix-WU-SCCM-DualScan.ps1

This commit is contained in:
2026-07-08 14:16:17 +02:00
parent 0361fc7645
commit bce4fda5b5
+87 -96
View File
@@ -1,112 +1,103 @@
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'SilentlyContinue'
$outDir = 'C:\install\missing_updates' Write-Host "[1/8] WU services stoppen..."
if (-not (Test-Path $outDir)) { Stop-Service wuauserv -Force
New-Item -Path $outDir -ItemType Directory -Force | Out-Null Stop-Service bits -Force
} Stop-Service cryptsvc -Force
$logFile = Join-Path $outDir 'missing_updates.txt'
if (Test-Path $logFile) { Remove-Item $logFile -Force }
function Log { Write-Host "[2/8] WUfB registry waarden verwijderen..."
param([string]$Text) $wu = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate'
Write-Host $Text $au = "$wu\AU"
Add-Content -Path $logFile -Value $Text
$keys = @(
'BranchReadinessLevel',
'DeferFeatureUpdates',
'DeferFeatureUpdatesPeriodInDays',
'DeferQualityUpdates',
'DeferQualityUpdatesPeriodInDays',
'ManagePreviewBuilds',
'ManagePreviewBuildsPolicyValue',
'PauseFeatureUpdates',
'PauseFeatureUpdatesStartTime',
'PauseQualityUpdates',
'PauseQualityUpdatesStartTime',
'ProductVersion',
'TargetReleaseVersion',
'TargetReleaseVersionInfo',
'DeferUpgrade',
'DeferUpgradePeriod',
'DeferUpdatePeriod',
'ExcludeWUDriversInQualityUpdate'
)
foreach ($k in $keys) {
Write-Host " - $k"
Remove-ItemProperty -Path $wu -Name $k -Force
} }
Log "Online WU scan (buiten WSUS om) - $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" Write-Host "[3/8] OS-specifieke fix bepalen..."
Log "Server: $env:COMPUTERNAME" $build = (Get-CimInstance Win32_OperatingSystem).BuildNumber
Log ('=' * 70) Write-Host " Build: $build"
if ($build -in 14393, 17763, 20348) {
# --- Online scan tegen Microsoft Update, WSUS negeren --- Write-Host " Server 2016/2019/2022: DisableDualScan = 1 zetten"
Log "" New-ItemProperty -Path $wu -Name 'DisableDualScan' -PropertyType DWord -Value 1 -Force | Out-Null
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
} }
if ($build -eq 26100) {
# --- Per update: details loggen en download-URL's verzamelen --- Write-Host " Server 2025: policy-driven update source waarden zetten"
$downloadList = @() $srcKeys = @(
'SetPolicyDrivenUpdateSourceForFeatureUpdates',
for ($i = 0; $i -lt $count; $i++) { 'SetPolicyDrivenUpdateSourceForQualityUpdates',
$u = $result.Updates.Item($i) 'SetPolicyDrivenUpdateSourceForDriverUpdates',
$kb = ($u.KBArticleIDs | ForEach-Object { "KB$_" }) -join ', ' 'SetPolicyDrivenUpdateSourceForOtherUpdates'
)
Log "" foreach ($k in $srcKeys) {
Log ("-" * 70) Write-Host " - $k"
Log "[$($i+1)/$count] $($u.Title)" New-ItemProperty -Path $wu -Name $k -PropertyType DWord -Value 1 -Force | Out-Null
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 }
}
}
}
} }
if (-not (Test-Path $au)) {
New-Item -Path $au -Force | Out-Null
}
New-ItemProperty -Path $au -Name 'UseUpdateClassPolicySource' -PropertyType DWord -Value 1 -Force | Out-Null
} }
# --- Download-URL's apart wegschrijven --- Write-Host "[4/8] WU cache leegmaken..."
$urlFile = Join-Path $outDir 'download_urls.txt' Remove-Item 'C:\Windows\SoftwareDistribution\DataStore\*' -Recurse -Force
$downloadList | ForEach-Object { $_.Url } | Sort-Object -Unique | Set-Content $urlFile Remove-Item 'C:\Windows\SoftwareDistribution\Download\*' -Recurse -Force
Log ""
Log ('=' * 70)
Log "Alle download-URL's staan in: $urlFile"
# --- Bestanden downloaden via BITS --- Write-Host "[5/8] WU services starten..."
Log "" Start-Service cryptsvc
Log "Downloaden naar $outDir ..." Start-Service bits
$n = 0 Start-Service wuauserv
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" Write-Host "[6/8] CcmExec stoppen (max 60 sec)..."
$svc = Get-Service ccmexec
if ($svc.Status -eq 'Running') {
Stop-Service ccmexec -Force
try { try {
Start-BitsTransfer -Source $item.Url -Destination $dest -ErrorAction Stop $svc.WaitForStatus('Stopped', (New-TimeSpan -Seconds 60))
$size = [math]::Round((Get-Item $dest).Length / 1MB, 1) Write-Host " CcmExec netjes gestopt"
Log " OK ($size MB)"
} }
catch { catch {
Log " MISLUKT: $($_.Exception.Message)" Write-Host " CcmExec hangt, force kill..."
Log " Handmatig downloaden via bovenstaande URL." Stop-Process -Name CcmExec -Force
Start-Sleep -Seconds 5
} }
} }
Log "" Write-Host "[7/8] CcmExec starten..."
Log ('=' * 70) Start-Service ccmexec
Log "Klaar: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" Start-Sleep -Seconds 10
Log "Rapport: $logFile"
Log "URL-lijst: $urlFile" Write-Host "[8/8] SCCM cycles triggeren..."
Log "Bestanden: $outDir" $triggers = @(
'{00000000-0000-0000-0000-000000000021}',
'{00000000-0000-0000-0000-000000000022}',
'{00000000-0000-0000-0000-000000000113}',
'{00000000-0000-0000-0000-000000000114}'
)
foreach ($t in $triggers) {
Write-Host " - Trigger $t"
Invoke-WmiMethod -Namespace root\ccm -Class SMS_Client -Name TriggerSchedule -ArgumentList $t | Out-Null
}
Write-Host ""
Write-Host "Klaar. Geef de scan 10-15 min voordat je Software Center checkt."