#Requires -Version 5.1 <# .SYNOPSIS Enable or disable deferred printer CustomActions in Product-Full.wxs (VM C gate). .DESCRIPTION Product-Full.wxs ships with printer/helper deferred CAs wrapped in DEFERRED_PRINTER_CAS:OFF … DEFERRED_PRINTER_CAS:OFF comment markers so candle/light stay files-only (VM B safe). -Enable (default): unwrap the body so WiX schedules CA_StopHelper, CA_InstallPrinters (+ rollback), CA_UninstallPrinters. Rebuild MSI, then run dual-ship VM C (DUAL-SHIP.md). Does not build, install, or sign. -Disable: re-wrap the body (default tree state). -Status: print enabled/disabled; exit 0 either way. dual-ship-smoke treats VM C as BLOCKED until CAs are enabled. Enabling here does not complete dual-ship — clean-VM C parity with NSIS is still required. .EXITCODES 0 Status printed, or file already in requested state, or toggle succeeded. 1 Product-Full.wxs missing, markers missing/ambiguous, or write failed. .PARAMETER WxsPath Path to Product-Full.wxs (default: sibling ../wix/Product-Full.wxs). .PARAMETER Enable Uncomment the deferred CA body (default action when neither -Disable nor -Status). .PARAMETER Disable Comment the deferred CA body again. .PARAMETER Status Report only; do not modify the file. .EXAMPLE powershell -NoProfile -ExecutionPolicy Bypass -File enable-printer-cas.ps1 -Status .EXAMPLE powershell -NoProfile -ExecutionPolicy Bypass -File enable-printer-cas.ps1 # then: build-full-msi.ps1 ; dual-ship-smoke.ps1 .EXAMPLE powershell -NoProfile -ExecutionPolicy Bypass -File enable-printer-cas.ps1 -Disable #> param( [string]$WxsPath = "", [switch]$Enable, [switch]$Disable, [switch]$Status ) $ErrorActionPreference = "Stop" if (($Enable.IsPresent -and $Disable.IsPresent) -or ($Enable.IsPresent -and $Status.IsPresent) -or ($Disable.IsPresent -and $Status.IsPresent)) { Write-Error "Use only one of -Enable, -Disable, or -Status." exit 1 } $mode = "enable" if ($Disable) { $mode = "disable" } elseif ($Status) { $mode = "status" } elseif ($Enable) { $mode = "enable" } $ScriptDir = $PSScriptRoot if (-not $WxsPath) { $WxsPath = Join-Path $ScriptDir "..\wix\Product-Full.wxs" } $WxsPath = $PSCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath($WxsPath) if (-not (Test-Path -LiteralPath $WxsPath)) { Write-Host ("FAIL: Product-Full.wxs not found: {0}" -f $WxsPath) -ForegroundColor Red exit 1 } # Marker pairs (non-overlapping strings): # disabled: # enabled: … $OffOpen = "" $OnOpen = "" $OnClose = "" $text = [System.IO.File]::ReadAllText($WxsPath) function Get-CasState([string]$Content) { $hasOff = $Content.Contains($OffOpen) -and $Content.Contains($OffClose) $hasOn = $Content.Contains($OnOpen) -and $Content.Contains($OnClose) if ($hasOff -and $hasOn) { return "ambiguous" } if ($hasOn) { return "enabled" } if ($hasOff) { return "disabled" } if ($Content.Contains("DEFERRED_PRINTER_CAS:")) { return "ambiguous" } return "missing" } $state = Get-CasState $text Write-Host ("Product-Full.wxs: {0}" -f $WxsPath) -ForegroundColor DarkGray Write-Host ("Deferred printer CAs: {0}" -f $state) if ($state -eq "missing" -or $state -eq "ambiguous") { Write-Host "FAIL: expected exactly one DEFERRED_PRINTER_CAS:OFF or :ON marker pair." -ForegroundColor Red Write-Host " See platform/windows/wix/README.md § Enable printer CAs (VM C)." -ForegroundColor DarkGray exit 1 } if ($mode -eq "status") { if ($state -eq "disabled") { Write-Host "VM C: BLOCKED until enable-printer-cas.ps1 (then rebuild MSI + clean-VM parity)." -ForegroundColor Yellow } else { Write-Host "VM C: CAs live in authoring — still need rebuild + dual-ship VM C sign-off." -ForegroundColor Cyan } exit 0 } if ($mode -eq "enable") { if ($state -eq "enabled") { Write-Host "Already enabled — no file change." -ForegroundColor Green Write-Host "Next: build-full-msi.ps1 then dual-ship-smoke / VM C checklist." -ForegroundColor DarkGray exit 0 } $idxOpen = $text.IndexOf($OffOpen) $idxClose = $text.IndexOf($OffClose) if ($idxOpen -lt 0 -or $idxClose -lt 0 -or $idxClose -le $idxOpen) { Write-Host "FAIL: OFF markers not found in order." -ForegroundColor Red exit 1 } $before = $text.Substring(0, $idxOpen) $bodyStart = $idxOpen + $OffOpen.Length $body = $text.Substring($bodyStart, $idxClose - $bodyStart) $after = $text.Substring($idxClose + $OffClose.Length) $text = $before + $OnOpen + $body + $OnClose + $after $label = "enabled" } else { if ($state -eq "disabled") { Write-Host "Already disabled — no file change." -ForegroundColor Green Write-Host "VM C remains BLOCKED (dual-ship-smoke)." -ForegroundColor DarkGray exit 0 } $idxOpen = $text.IndexOf($OnOpen) $idxClose = $text.IndexOf($OnClose) if ($idxOpen -lt 0 -or $idxClose -lt 0 -or $idxClose -le $idxOpen) { Write-Host "FAIL: ON markers not found in order." -ForegroundColor Red exit 1 } $before = $text.Substring(0, $idxOpen) $bodyStart = $idxOpen + $OnOpen.Length $body = $text.Substring($bodyStart, $idxClose - $bodyStart) $after = $text.Substring($idxClose + $OnClose.Length) $text = $before + $OffOpen + $body + $OffClose + $after $label = "disabled" } $utf8NoBom = New-Object System.Text.UTF8Encoding $false [System.IO.File]::WriteAllText($WxsPath, $text, $utf8NoBom) $verify = Get-CasState $text if ($verify -ne $label) { Write-Host ("FAIL: after write, state is '{0}' (expected '{1}')." -f $verify, $label) -ForegroundColor Red exit 1 } Write-Host ("OK: deferred printer CAs {0} in Product-Full.wxs" -f $label) -ForegroundColor Green if ($label -eq "enabled") { Write-Host "Next:" -ForegroundColor DarkGray Write-Host " 1) powershell -File platform\windows\scripts\build-full-msi.ps1" Write-Host " 2) dual-ship-smoke.ps1 (VM C no longer authoring-blocked; clean-VM still required)" Write-Host " 3) VM C parity vs VM A per DUAL-SHIP.md / VM-DUAL-SHIP-CHECKLIST.md" Write-Host "Do not thin NSIS until dual-ship exit checklist A–D is checked." -ForegroundColor DarkGray } else { Write-Host "VM C: BLOCKED again until CAs re-enabled. Files-only MSI (VM B) remains the safe path." -ForegroundColor Yellow } exit 0