diff --git a/template/Install-CIToolchain-WinBuild2022.ps1 b/template/Install-CIToolchain-WinBuild2022.ps1 index 5d72d0e..a45b31f 100644 --- a/template/Install-CIToolchain-WinBuild2022.ps1 +++ b/template/Install-CIToolchain-WinBuild2022.ps1 @@ -253,6 +253,41 @@ function Invoke-DiskCleanup { foreach ($svc in 'wuauserv', 'UsoSvc', 'bits', 'dosvc', 'TrustedInstaller') { Stop-Service -Name $svc -Force -ErrorAction SilentlyContinue } + + # Pin Windows Update down for the WHOLE DISM /ResetBase window below. /ResetBase + # drives heavy CBS servicing (TiWorker); with wuauserv merely *stopped* and no + # ACL yet, WaaSMedicSvc wakes, flips wuauserv Start back to Manual, and a + # "Schedule Scan" task starts it mid-cleanup — so an interruption here leaves WU + # running (exactly the half-prepared state seen on stuck templates). Force + # Start=4, deny WaaSMedicSvc the registry write, and disable the scan tasks + # BEFORE DISM, not only in the re-enforce after it. + Set-Service -Name wuauserv -StartupType Disabled -ErrorAction SilentlyContinue + Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv' ` + -Name Start -Value 4 -Type DWord -Force -ErrorAction SilentlyContinue + try { + $svcRegPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv' + $acl = Get-Acl $svcRegPath + $denyRule = New-Object System.Security.AccessControl.RegistryAccessRule( + ([System.Security.Principal.NTAccount]'NT SERVICE\WaaSMedicSvc'), + [System.Security.AccessControl.RegistryRights]'SetValue,CreateSubKey,WriteKey', + [System.Security.AccessControl.InheritanceFlags]::None, + [System.Security.AccessControl.PropagationFlags]::None, + [System.Security.AccessControl.AccessControlType]::Deny + ) + $acl.AddAccessRule($denyRule) + Set-Acl $svcRegPath $acl + Write-Host "wuauserv: WaaSMedicSvc write-deny ACL applied (pre-DISM)." + } catch { + Write-Warning "wuauserv pre-DISM ACL deny skipped (non-fatal): $_" + } + foreach ($t in @( + '\Microsoft\Windows\WindowsUpdate\Scheduled Start', + '\Microsoft\Windows\UpdateOrchestrator\Schedule Scan', + '\Microsoft\Windows\UpdateOrchestrator\Schedule Scan Static Task' + )) { + schtasks /Change /TN $t /Disable 2>&1 | Out-Null + } + $sdDownload = 'C:\Windows\SoftwareDistribution\Download' Remove-Item $sdDownload -Recurse -Force -ErrorAction SilentlyContinue New-Item -ItemType Directory -Path $sdDownload -Force | Out-Null diff --git a/template/Install-CIToolchain-WinBuild2025.ps1 b/template/Install-CIToolchain-WinBuild2025.ps1 index 203ba1d..82ef2b5 100644 --- a/template/Install-CIToolchain-WinBuild2025.ps1 +++ b/template/Install-CIToolchain-WinBuild2025.ps1 @@ -254,6 +254,41 @@ function Invoke-DiskCleanup { foreach ($svc in 'wuauserv', 'UsoSvc', 'bits', 'dosvc', 'TrustedInstaller') { Stop-Service -Name $svc -Force -ErrorAction SilentlyContinue } + + # Pin Windows Update down for the WHOLE DISM /ResetBase window below. /ResetBase + # drives heavy CBS servicing (TiWorker); with wuauserv merely *stopped* and no + # ACL yet, WaaSMedicSvc wakes, flips wuauserv Start back to Manual, and a + # "Schedule Scan" task starts it mid-cleanup — so an interruption here leaves WU + # running (exactly the half-prepared state seen on stuck templates). Force + # Start=4, deny WaaSMedicSvc the registry write, and disable the scan tasks + # BEFORE DISM, not only in the re-enforce after it. + Set-Service -Name wuauserv -StartupType Disabled -ErrorAction SilentlyContinue + Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv' ` + -Name Start -Value 4 -Type DWord -Force -ErrorAction SilentlyContinue + try { + $svcRegPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv' + $acl = Get-Acl $svcRegPath + $denyRule = New-Object System.Security.AccessControl.RegistryAccessRule( + ([System.Security.Principal.NTAccount]'NT SERVICE\WaaSMedicSvc'), + [System.Security.AccessControl.RegistryRights]'SetValue,CreateSubKey,WriteKey', + [System.Security.AccessControl.InheritanceFlags]::None, + [System.Security.AccessControl.PropagationFlags]::None, + [System.Security.AccessControl.AccessControlType]::Deny + ) + $acl.AddAccessRule($denyRule) + Set-Acl $svcRegPath $acl + Write-Host "wuauserv: WaaSMedicSvc write-deny ACL applied (pre-DISM)." + } catch { + Write-Warning "wuauserv pre-DISM ACL deny skipped (non-fatal): $_" + } + foreach ($t in @( + '\Microsoft\Windows\WindowsUpdate\Scheduled Start', + '\Microsoft\Windows\UpdateOrchestrator\Schedule Scan', + '\Microsoft\Windows\UpdateOrchestrator\Schedule Scan Static Task' + )) { + schtasks /Change /TN $t /Disable 2>&1 | Out-Null + } + $sdDownload = 'C:\Windows\SoftwareDistribution\Download' Remove-Item $sdDownload -Recurse -Force -ErrorAction SilentlyContinue New-Item -ItemType Directory -Path $sdDownload -Force | Out-Null