From b4927236cd5ccc29047d532a17427854e2253c6c Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Mon, 1 Jun 2026 22:16:58 +0000 Subject: [PATCH] kms-website: add consent-gated deep repair for wedged SXSMSI/1603 Office install When the Office VL install fails with setup.exe 1603 (C2R 'SXSMSI' prereq) AND no reboot is pending AND the common causes are clean (verified via telemetry: msiserver healthy, EventLog running, no DisableMSI policy, no stale InProgress MSI, disk OK) AND a manual DISM/SFC + reboot did not help, the install subsystem itself is wedged. New Repair-OfficePrereq (consent-gated; $env:KMS_DEEP_REPAIR=1 to auto-consent) goes one level past DISM without uninstalling anything: re-registers the Windows Installer engine (msiexec /unregister + /regserver) and resets the servicing/update caches (SoftwareDistribution + catroot2), then prompts a restart and re-run. Offered automatically from Reinstall-OfficeVL on a 1603 with no pending reboot. ODT exit code now exposed via $script:OdtExitCode. --- static/scripts/kms-bootstrap.ps1 | 44 +++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/static/scripts/kms-bootstrap.ps1 b/static/scripts/kms-bootstrap.ps1 index 2d5a3e4..072e969 100644 --- a/static/scripts/kms-bootstrap.ps1 +++ b/static/scripts/kms-bootstrap.ps1 @@ -361,6 +361,7 @@ function Invoke-Odt([string]$configXml, [string]$stepMsg) { Step $stepMsg $p = Start-Process -FilePath $setup -ArgumentList '/configure', "`"$cfg`"" -Wait -PassThru $code = $p.ExitCode + $script:OdtExitCode = $code # 0 = success, 3010 = success/reboot-required. Anything else is a real ODT # failure - surface the log tail (carries the error code) so we can diagnose. if ($code -ne 0 -and $code -ne 3010) { @@ -381,6 +382,42 @@ function Invoke-Odt([string]$configXml, [string]$stepMsg) { finally { Remove-Item -Recurse -Force $tmp -ErrorAction SilentlyContinue } } +# Deep repair for a wedged Office-install prerequisite (the C2R 'SXSMSI' check +# fails with 1603) when the common causes are clean AND DISM/SFC did not help. +# Goes one level past DISM: re-registers the Windows Installer engine and resets +# the servicing/update caches (SoftwareDistribution + catroot2) - which fixes +# MSI-engine / signature-catalog corruption that DISM/SFC leave untouched. It +# UNINSTALLS NOTHING. A restart is required afterwards. Consent-gated; set +# $env:KMS_DEEP_REPAIR=1 to auto-consent. +function Repair-OfficePrereq { + $msg = @" +The Office installer's prerequisite check keeps failing (SXSMSI / error 1603) and +the usual causes are clean (no pending reboot, Windows Installer healthy, disk OK, +no policy block). A DEEP REPAIR can fix the Windows install subsystem - it does NOT +uninstall anything: + * re-register the Windows Installer engine (msiexec /unregister + /regserver) + * reset the Windows servicing/update caches (SoftwareDistribution + catroot2) +A RESTART is required afterwards, then re-run this one-liner to install Office. +"@ + if (-not (Approve $msg ([bool]$env:KMS_DEEP_REPAIR))) { Warn "Deep repair skipped."; return $false } + Send-Diag 'odt' 'deep-repair-start' (Get-OfficeState) + Step "Re-registering the Windows Installer engine" + Start-Process -FilePath 'msiexec.exe' -ArgumentList '/unregister' -Wait -ErrorAction SilentlyContinue + Start-Process -FilePath 'msiexec.exe' -ArgumentList '/regserver' -Wait -ErrorAction SilentlyContinue + Step "Resetting servicing/update caches (SoftwareDistribution, catroot2)" + foreach ($s in 'wuauserv', 'cryptSvc', 'bits', 'msiserver') { Stop-Service $s -Force -ErrorAction SilentlyContinue } + $stamp = Get-Date -Format 'yyyyMMddHHmmss' + foreach ($p in @("$env:WINDIR\SoftwareDistribution", "$env:WINDIR\System32\catroot2")) { + if (Test-Path $p) { Rename-Item -LiteralPath $p -NewName "$(Split-Path $p -Leaf).old-$stamp" -ErrorAction SilentlyContinue } + } + foreach ($s in 'cryptSvc', 'bits', 'wuauserv') { Start-Service $s -ErrorAction SilentlyContinue } + OK "Deep repair complete." + Write-Host "" + Write-Host "==> NOW restart the PC (Start -> Power -> RESTART, not Shut down), then re-run the one-liner." -ForegroundColor Yellow + Send-Diag 'odt' 'deep-repair-done' (Get-OfficeState) + return $true +} + function Reinstall-OfficeVL([string]$product, [string]$channel) { # An Office-blocking pending reboot (CBS/WU, or an Office file-rename) fails the # C2R 'SXSMSI' prereq with 1603. Stop before the ~3 GB download and tell the user @@ -413,7 +450,12 @@ function Reinstall-OfficeVL([string]$product, [string]$channel) { # Snapshot the pre-install state so a failure is debuggable even if the user # aborts the ~3 GB download (the event ships before the install starts). Send-Diag 'odt' 'preinstall-state' (Get-OfficeState) - if (-not (Invoke-Odt $xml "Installing $product (multi-GB download + reinstall; several minutes)")) { return $false } + if (-not (Invoke-Odt $xml "Installing $product (multi-GB download + reinstall; several minutes)")) { + # SXSMSI/1603 with no pending reboot = the Windows install subsystem itself is + # wedged (survives DISM/SFC). Offer the deep repair, then reboot + re-run. + if ($script:OdtExitCode -eq 1603 -and -not (Test-OfficeRebootPending)) { Repair-OfficePrereq | Out-Null } + return $false + } # setup.exe returning is NOT proof Office is on disk - verify it actually landed. if (Wait-OfficeInstalled $product) { OK "$product installed"; return $true } $reboot = Test-PendingReboot