Setup.ps1 加 WU 暫停/恢復;unattend.xml Order 5 收 stderr 進 log

- Setup.ps1 開頭暫停 Windows Update(PauseUpdatesExpiryTime + 停 wuauserv/UsoSvc/BITS),
  結尾解暫停 + UsoClient 觸發掃描,避免跟 post-install 搶頻寬/CPU
- Win11Debloat config 從 here-string 改成 hashtable + ConvertTo-Json,
  繞開 PowerShell 5.1 ANSI 讀取時 here-string parse 失敗的 case
- Log 函式加 Write-Host,console 視窗能即時看 START/DONE
- unattend.xml Order 5 把 stdout+stderr 全部 redirect 到 firstlogon-runsetup.log,
  Setup.ps1 連 parse error 都會留紀錄;Order 3 改空密碼 + 強制改密
This commit is contained in:
2026-04-28 08:35:20 +08:00
parent b1e5b6912a
commit ef9f5d16bc
2 changed files with 84 additions and 59 deletions

135
Setup.ps1
View File

@@ -5,8 +5,10 @@
#
# Log: C:\Windows\Temp\setup.log每段都寫 START/DONE/ERR
#
# 順序:先做不需網路的本機設定(防火牆 / 註冊機碼 / Default profile
# 再等網路最後跑下載安裝OpenSSH FoD / KMS / winget / RemoveAI / Win11Debloat / Telegram
# 順序:開頭先暫停 Windows Update避免跟本腳本搶頻寬CPU
# 再做不需網路的本機設定(防火牆 / 註冊機碼 / Default profile
# 接著等網路跑下載安裝OpenSSH FoD / KMS / winget / RemoveAI / Win11Debloat / Telegram
# 結尾解除 WU 暫停並主動觸發掃描,這樣更新會排在所有 post-install 之後才開始下載。
$ErrorActionPreference = 'Continue'
$ProgressPreference = 'SilentlyContinue'
@@ -30,60 +32,30 @@ $UwpRemoveList = @(
'Microsoft.PowerAutomateDesktop','Microsoft.Windows.Photos'
)
# Win11Debloat 的設定 JSON(與 toolkit/config/win11debloat-config.json 同步)
$Win11DebloatConfigJson = @'
{
"Version": "1.0",
"Tweaks": [
{ "Name": "RemoveApps", "Value": true },
{ "Name": "RemoveGamingApps", "Value": true },
{ "Name": "RemoveCommApps", "Value": true },
{ "Name": "RemoveW11Outlook", "Value": true },
{ "Name": "DisableTelemetry", "Value": true },
{ "Name": "DisableSearchHistory", "Value": true },
{ "Name": "DisableBing", "Value": true },
{ "Name": "DisableStoreSearchSuggestions", "Value": true },
{ "Name": "DisableSearchHighlights", "Value": true },
{ "Name": "DisableLockscreenTips", "Value": true },
{ "Name": "DisableSuggestions", "Value": true },
{ "Name": "DisableDesktopSpotlight", "Value": true },
{ "Name": "DisableFindMyDevice", "Value": true },
{ "Name": "DisableEdgeAds", "Value": true },
{ "Name": "DisableBraveBloat", "Value": true },
{ "Name": "DisableSettings365Ads", "Value": true },
{ "Name": "DisableSettingsHome", "Value": true },
{ "Name": "DisableCopilot", "Value": true },
{ "Name": "DisableRecall", "Value": true },
{ "Name": "DisableClickToDo", "Value": true },
{ "Name": "DisableAISvcAutoStart", "Value": true },
{ "Name": "DisablePaintAI", "Value": true },
{ "Name": "DisableNotepadAI", "Value": true },
{ "Name": "DisableEdgeAI", "Value": true },
{ "Name": "PreventUpdateAutoReboot", "Value": true },
{ "Name": "DisableModernStandbyNetworking", "Value": true },
{ "Name": "DisableDVR", "Value": true },
{ "Name": "DisableGameBarIntegration", "Value": true },
{ "Name": "ShowHiddenFolders", "Value": true },
{ "Name": "ShowKnownFileExt", "Value": true },
{ "Name": "EnableDarkMode", "Value": true },
{ "Name": "TaskbarAlignLeft", "Value": true },
{ "Name": "HideSearchTb", "Value": true },
{ "Name": "HideTaskview", "Value": true },
{ "Name": "HideChat", "Value": true },
{ "Name": "DisableWidgets", "Value": true },
{ "Name": "DisableStartRecommended", "Value": true },
{ "Name": "Hide3dObjects", "Value": true },
{ "Name": "ExplorerToThisPC", "Value": true },
{ "Name": "HideGallery", "Value": true },
{ "Name": "DisableDragTray", "Value": true }
],
"Deployment": [
{ "Name": "CreateRestorePoint", "Value": true },
{ "Name": "RestartExplorer", "Value": false },
{ "Name": "AppRemovalScopeIndex", "Value": 0 }
]
# Win11Debloat 的設定(與 toolkit/config/win11debloat-config.json 同步)
# 改用 hashtable + ConvertTo-Json避免 here-string 在某些 PowerShell 環境 parse 失敗
$Win11DebloatTweakNames = @(
'RemoveApps','RemoveGamingApps','RemoveCommApps','RemoveW11Outlook',
'DisableTelemetry','DisableSearchHistory','DisableBing','DisableStoreSearchSuggestions',
'DisableSearchHighlights','DisableLockscreenTips','DisableSuggestions','DisableDesktopSpotlight',
'DisableFindMyDevice','DisableEdgeAds','DisableBraveBloat','DisableSettings365Ads',
'DisableSettingsHome','DisableCopilot','DisableRecall','DisableClickToDo',
'DisableAISvcAutoStart','DisablePaintAI','DisableNotepadAI','DisableEdgeAI',
'PreventUpdateAutoReboot','DisableModernStandbyNetworking','DisableDVR','DisableGameBarIntegration',
'ShowHiddenFolders','ShowKnownFileExt','EnableDarkMode','TaskbarAlignLeft',
'HideSearchTb','HideTaskview','HideChat','DisableWidgets','DisableStartRecommended',
'Hide3dObjects','ExplorerToThisPC','HideGallery','DisableDragTray'
)
$Win11DebloatConfig = [ordered]@{
Version = '1.0'
Tweaks = @($Win11DebloatTweakNames | ForEach-Object { [ordered]@{ Name = $_; Value = $true } })
Deployment = @(
[ordered]@{ Name = 'CreateRestorePoint'; Value = $true },
[ordered]@{ Name = 'RestartExplorer'; Value = $false },
[ordered]@{ Name = 'AppRemovalScopeIndex'; Value = 0 }
)
}
'@
$Win11DebloatConfigJson = $Win11DebloatConfig | ConvertTo-Json -Depth 5
# ---- helpers ----
@@ -91,6 +63,7 @@ function Log {
param([string]$msg)
$line = '[{0}] {1}' -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $msg
Add-Content -Path $LogFile -Value $line -Encoding UTF8
Write-Host $line
}
function Section {
@@ -126,6 +99,25 @@ function Set-RegValue {
# ---- Phase 1: 本機設定(不需網路)----
Section 'pause-windows-update' {
# 設定官方暫停旗標:暫停 24 小時Setup.ps1 結尾會主動清掉並觸發掃描)
$now = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
$expiry = (Get-Date).ToUniversalTime().AddHours(24).ToString("yyyy-MM-ddTHH:mm:ssZ")
$ux = 'HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings'
Set-RegValue $ux 'PauseUpdatesStartTime' $now 'String'
Set-RegValue $ux 'PauseUpdatesExpiryTime' $expiry 'String'
Set-RegValue $ux 'PauseFeatureUpdatesStartTime' $now 'String'
Set-RegValue $ux 'PauseFeatureUpdatesEndTime' $expiry 'String'
Set-RegValue $ux 'PauseQualityUpdatesStartTime' $now 'String'
Set-RegValue $ux 'PauseQualityUpdatesEndTime' $expiry 'String'
Log "WU paused until $expiry (UTC)"
# 停掉已啟動的 WU 相關服務,避免在 Setup.ps1 期間搶頻寬CPU
foreach ($svc in @('UsoSvc','wuauserv','BITS')) {
Stop-Service -Name $svc -Force -ErrorAction SilentlyContinue
}
}
Section 'firewall-ssh-22' {
Remove-NetFirewallRule -DisplayName 'SSH TCP 22 (Allow Inbound)' -ErrorAction SilentlyContinue
New-NetFirewallRule -DisplayName 'SSH TCP 22 (Allow Inbound)' `
@@ -324,6 +316,39 @@ Section 'install-telegram' {
Log "Telegram installer exit code: $($proc.ExitCode)"
}
Section 'resume-and-trigger-windows-update' {
# 清掉暫停旗標pause-windows-update 設的那幾個值)
$ux = 'HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings'
foreach ($n in @('PauseUpdatesStartTime','PauseUpdatesExpiryTime',
'PauseFeatureUpdatesStartTime','PauseFeatureUpdatesEndTime',
'PauseQualityUpdatesStartTime','PauseQualityUpdatesEndTime')) {
Remove-ItemProperty -Path $ux -Name $n -ErrorAction SilentlyContinue
}
# 確保服務可啟動
foreach ($svc in @('BITS','wuauserv','UsoSvc')) {
Start-Service -Name $svc -ErrorAction SilentlyContinue
}
# 通知 Update Orchestrator 重新讀設定,然後立即掃描/下載/安裝
$uso = "$env:SystemRoot\System32\UsoClient.exe"
if (Test-Path $uso) {
& $uso RefreshSettings | Out-Null
& $uso StartScan | Out-Null
& $uso StartDownload | Out-Null
& $uso StartInstall | Out-Null
Log 'WU resumed; UsoClient scan/download/install triggered'
} else {
# 後備:呼叫 COM 觸發掃描
try {
(New-Object -ComObject Microsoft.Update.AutoUpdate).DetectNow()
Log 'WU resumed; AutoUpdate.DetectNow triggered (COM fallback)'
} catch {
Log "WU resumed but trigger failed: $($_.Exception.Message)"
}
}
}
# 結尾:刪掉殘留的明碼回應檔
Section 'cleanup-unattend-files' {
Remove-Item 'C:\Windows\Panther\unattend.xml' -Force -ErrorAction SilentlyContinue

View File

@@ -169,8 +169,8 @@
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>3</Order>
<CommandLine>cmd.exe /c "net user User 1234 /add &amp; net user User /logonpasswordchg:yes"</CommandLine>
<Description>建立本機帳號 User密碼 1234,首次登入強制改密</Description>
<CommandLine>cmd.exe /c "net user User /add &amp; net user User /logonpasswordchg:yes"</CommandLine>
<Description>建立本機帳號 User密碼,首次登入強制設定新密碼</Description>
<RequiresUserInput>false</RequiresUserInput>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
@@ -181,8 +181,8 @@
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>5</Order>
<CommandLine>cmd.exe /c "if exist C:\Scripts\Setup.ps1 (powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\Scripts\Setup.ps1) else (echo SETUP_NOT_FOUND %DATE% %TIME% &gt; C:\Windows\Temp\firstlogon-runsetup.log)"</CommandLine>
<Description>執行 Setup.ps113 項 post-installSSH/RDP/WinRM/KMS/Chrome/Debloat/Telegram/RemoveAI/UI/IME/重命名帳號…log: C:\Windows\Temp\setup.log</Description>
<CommandLine>cmd.exe /c "(echo == firstlogon-runsetup %DATE% %TIME% == &amp; if exist C:\Scripts\Setup.ps1 (powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\Scripts\Setup.ps1) else (echo SETUP_NOT_FOUND)) &gt; C:\Windows\Temp\firstlogon-runsetup.log 2&gt;&amp;1"</CommandLine>
<Description>執行 Setup.ps1所有 stdout/stderr 都收到 firstlogon-runsetup.log含 parse error正常 Setup.ps1 自身寫到 setup.log</Description>
<RequiresUserInput>false</RequiresUserInput>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">