From 96ea0d583231f1ea3dd2ba6c812c99425d5aadf2 Mon Sep 17 00:00:00 2001 From: Timmy Date: Sun, 19 Apr 2026 10:30:53 +0800 Subject: [PATCH] =?UTF-8?q?Initial=20commit:=20Windows=20unattend.xml=20?= =?UTF-8?q?=E8=87=AA=E5=8B=95=E9=83=A8=E7=BD=B2=E7=AF=84=E6=9C=AC=E8=88=87?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QUICKSTART.md | 151 +++++++++++++++++++++++++++++++++++++++++++++ README.md | 112 +++++++++++++++++++++++++++++++++ SUMMARY.md | 94 ++++++++++++++++++++++++++++ unattend.xml | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 525 insertions(+) create mode 100644 QUICKSTART.md create mode 100644 README.md create mode 100644 SUMMARY.md create mode 100644 unattend.xml diff --git a/QUICKSTART.md b/QUICKSTART.md new file mode 100644 index 0000000..3c05dbd --- /dev/null +++ b/QUICKSTART.md @@ -0,0 +1,151 @@ +# QUICKSTART — 從零到自動安裝 Windows + +照著做一次就能跑出一個「插上 USB → 自動裝完 Windows → 自動登入 → 跑 Setup.ps1 → 重開機」的流程。 + +> 預設情境:x64、UEFI+GPT、繁體中文、單一 Disk 0。 + +--- + +## 0. 事前準備 + +需要準備: + +- [ ] Windows 10 或 11 官方 ISO(從 [microsoft.com](https://www.microsoft.com/software-download) 取得) +- [ ] 一支 ≥ 8 GB 的 USB 隨身碟(會被格式化) +- [ ] 一台測試機或 VM(強烈建議先在 VM 驗證) +- [ ] 本專案的 `unattend.xml` + +**編輯 `unattend.xml` 的必改項目:** + +| 行為 | 原值 | 要改成 | +|---|---|---| +| 產品序號 | `XXXXX-XXXXX-XXXXX-XXXXX-XXXXX` | 你的序號,或 KMS 通用金鑰,或整個 `` 節點刪掉 | +| 管理員密碼 | `P@ssw0rd!`(兩處:`LocalAccount` 與 `AutoLogon`) | 你的密碼 | +| 組織名 | `YourCompany` | 你的組織 | +| 腳本路徑 | `C:\Scripts\Setup.ps1` | 留著或改路徑;不要執行就刪 `` | + +--- + +## 1. 做一支自動安裝 USB + +### 選項 A:Rufus(最快,Windows 原生) + +1. 下載 [Rufus](https://rufus.ie/) 並開啟 +2. 選 ISO、選 USB、分割配置選 **GPT**、目標選 **UEFI** +3. 按「開始」寫入 +4. 寫入完成後,把 `unattend.xml` **改名為 `autounattend.xml`** 放到 USB 根目錄 + +### 選項 B:macOS / Linux 手動方式 + +```bash +# macOS:找到 USB +diskutil list +# 假設是 /dev/disk4 +diskutil eraseDisk MS-DOS "WINUSB" GPT /dev/disk4 + +# 掛載 ISO 並複製 +hdiutil mount Windows.iso +cp -R /Volumes/CCCOMA_X64FRE_ZH-TW_DV9/* /Volumes/WINUSB/ + +# 放入 autounattend.xml +cp unattend.xml /Volumes/WINUSB/autounattend.xml +``` + +> Linux 用 `wimlib-imagex split` 處理超過 FAT32 4GB 限制的 `install.wim`。 + +--- + +## 2. 先在 VM 試跑(強烈建議) + +跳過這步 = 在真機上賭運氣。 + +### Hyper-V + +```powershell +New-VM -Name "WinTest" -Generation 2 -MemoryStartupBytes 4GB -NewVHDPath "C:\VM\WinTest.vhdx" -NewVHDSizeBytes 60GB +Set-VMDvdDrive -VMName "WinTest" -Path "C:\ISO\Windows.iso" +Set-VMFirmware -VMName "WinTest" -EnableSecureBoot Off # 測試期間關掉比較省事 +Start-VM "WinTest" +``` + +把 `autounattend.xml` 注入 ISO:用 [AnyBurn](https://www.anyburn.com/) / `oscdimg` 在 ISO 根目錄加入該檔,或在 VM 掛第二顆 CD。 + +### VirtualBox / VMware + +建一台 UEFI 開機的 VM,掛改好的 ISO 開機即可。 + +--- + +## 3. 跑起來會看到什麼 + +| 階段 | 畫面 | 時間 | +|---|---|---| +| WinPE 啟動 | Windows 標誌、載入條 | 30–60 秒 | +| 磁碟分割 + 映像展開 | 「正在安裝 Windows」百分比 | 5–15 分鐘 | +| 第一次重開 | 黑屏 → 「請稍候」 | 1–2 分鐘 | +| OOBE 略過 | **不該出現任何選單**;直接跳過 | 秒殺 | +| AutoLogon | 以 `Admin` 自動登入到桌面 | — | +| FirstLogonCommands | 閃出 PowerShell 視窗跑 `Setup.ps1` | 看腳本內容 | +| 重開機 | 5 秒倒數後重啟 | — | + +**正常就是全程不需要碰鍵盤滑鼠。** 如果中途卡在 OOBE 畫面要你選語系/建帳號 → 去看第 5 節除錯。 + +--- + +## 4. 部署後善後 + +第一次自動登入完成後,建議做這三件事: + +1. **刪除殘留的回應檔**(含明碼密碼): + ```powershell + Remove-Item C:\Windows\Panther\unattend.xml -Force -ErrorAction SilentlyContinue + Remove-Item C:\Windows\Panther\Unattend\unattend.xml -Force -ErrorAction SilentlyContinue + ``` + 建議加到 `Setup.ps1` 結尾。 + +2. **關掉 AutoLogon**(本範本靠 `LogonCount=1` 會自動失效,驗證一下): + ```powershell + reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon + ``` + +3. **改密碼**:範本密碼 `P@ssw0rd!` 是給自動化用的,上線前換掉。 + +--- + +## 5. 除錯:沒跑完或卡住時 + +### 看日誌 + +Windows Setup 把所有 unattend 執行記錄放在: + +| 階段 | 路徑 | +|---|---| +| WinPE | `X:\Windows\Panther\setupact.log`(WinPE 執行期間) | +| 安裝中 | `C:\Windows\Panther\setupact.log` | +| OOBE/Specialize | `C:\Windows\Panther\UnattendGC\setupact.log` | +| FirstLogonCommands 錯誤 | 開 Event Viewer → Windows Logs → Application | + +Shift + F10 在任何安裝畫面會開出命令提示字元,可以 `notepad` 看 log。 + +### 常見錯誤 + +| 現象 | 原因 | 解法 | +|---|---|---| +| 停在選語系畫面 | `autounattend.xml` 沒讀到 | 檔名拼錯/不在根目錄;確認 USB 格式 FAT32 | +| 磁碟分割失敗 | 目標機是 BIOS/MBR | 改 ``:拿掉 EFI/MSR,用 MBR + System Reserved | +| `ProductKey` 錯誤 | 序號無效 | 改正確序號、用 KMS 通用金鑰、或刪掉整個 `` 節點 | +| OOBE 沒略過 | Windows 版本不支援該欄位 | 比對當前版本 SIM 可用欄位 | +| FirstLogonCommands 沒跑 | `AutoLogon` 沒設或 `Order` 重複 | 確認 `AutoLogon.Enabled=true` 且 `Order` 不重複 | +| `Setup.ps1` 找不到 | 路徑不存在 | 先用其他方式把腳本放到 `C:\Scripts\`,或改用 `FirstLogonCommands` 從 USB 複製 | + +### 驗證 XML 語法 + +用 Windows SIM 開啟(會 schema-validate),或任何支援 XSD 的編輯器。 + +--- + +## 6. 下一步 + +- 讀 `README.md` 了解每個欄位在做什麼 +- 看 `SUMMARY.md` 了解整體設計脈絡 +- 改完記得 Commit 一份給自己留底 diff --git a/README.md b/README.md new file mode 100644 index 0000000..9dc3cb3 --- /dev/null +++ b/README.md @@ -0,0 +1,112 @@ +# Windows Unattend 自動部署 + +以 `unattend.xml` 回應檔自動化 Windows 10/11 安裝流程。涵蓋語系、磁碟分割、帳號建立、產品序號、首次登入腳本執行。 + +--- + +## 檔案 + +| 檔案 | 用途 | +|---|---| +| `unattend.xml` | 主回應檔,放入 USB/ISO 時需改名為 `autounattend.xml` | +| `QUICKSTART.md` | 操作步驟:如何產生 USB、掛載 ISO、跑 VM 測試 | +| `SUMMARY.md` | 本專案的來由與設計脈絡 | + +--- + +## Pass 架構 + +Windows Setup 在不同階段套用不同 ``: + +| Pass | 時機 | 本檔負責 | +|---|---|---| +| `windowsPE` | WinPE 啟動、安裝前 | UI 語系、磁碟分割(UEFI+GPT)、產品序號、EULA | +| `specialize` | 映像套用後、第一次開機前 | 電腦名稱、時區、擁有者資訊 | +| `oobeSystem` | 首次開機 OOBE 階段 | 略過 OOBE、建立本機帳號、AutoLogon、FirstLogonCommands | + +--- + +## 元件與設定項 + +### windowsPE + +- **Microsoft-Windows-International-Core-WinPE** — `SetupUILanguage` / `InputLocale` / `SystemLocale` / `UILanguage` / `UserLocale` 皆為 `zh-TW`,`InputLocale` 為 `0404:00000404`(繁中鍵盤)。 +- **Microsoft-Windows-Setup** + - `DiskConfiguration` — 清空 Disk 0,建立三個分割: + - EFI 500 MB(FAT32, Label `System`) + - MSR 128 MB + - Primary 其餘全部(NTFS, Label `Windows`, 掛 `C:`) + - `ImageInstall` — 安裝到 Disk 0 Partition 3 + - `UserData` — `ProductKey`(範本為 `XXXXX-XXXXX-XXXXX-XXXXX-XXXXX`,KMS 可用通用金鑰)、`AcceptEula=true`、`FullName`、`Organization` + +### specialize + +- **Microsoft-Windows-Shell-Setup** + - `ComputerName` — `PC-%RAND:5%`(5 位隨機數字) + - `TimeZone` — `Taipei Standard Time` + - `RegisteredOwner` / `RegisteredOrganization` + +### oobeSystem + +- **Microsoft-Windows-International-Core** — 重複設定語系(OOBE 階段需要) +- **Microsoft-Windows-Shell-Setup** + - `OOBE` — 全部略過:EULA、OEM 註冊、線上帳號、無線設定、機器與使用者 OOBE;`NetworkLocation=Work`、`ProtectYourPC=3` + - `UserAccounts.LocalAccounts` — 建立 `Admin`(Administrators 群組,密碼 `P@ssw0rd!`,明碼) + - `AutoLogon` — 以 `Admin` 自動登入一次(`LogonCount=1`) + - `FirstLogonCommands` — 按 `Order` 依序執行: + 1. `powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\Setup.ps1` + 2. `cmd.exe /c net accounts /maxpwage:unlimited`(密碼永不過期) + 3. `shutdown /r /t 5`(重開機) + +--- + +## 關鍵參數參考 + +| 參數 | 說明 | +|---|---| +| `processorArchitecture` | x64 用 `amd64`、ARM64 用 `arm64` | +| `publicKeyToken` | 微軟元件簽章,固定 `31bf3856ad364e35` | +| `ProductKey` | 零售/OEM 填正式序號;KMS/大量授權可用 Generic Volume License Key,或留空 | +| `PlainText` | `true` 用明碼、`false` 用 Base64(SIM 會自動產生) | +| `%RAND:5%` | 內建變數,產生 5 位隨機數字避免主機名衝突 | +| `WillShowUI` | `OnError` / `Always` / `Never` | +| `FirstLogonCommands` | 需搭配 `AutoLogon` 才會觸發;按 `Order` 同步執行 | + +--- + +## 放置位置(擇一) + +| 位置 | 檔名 | +|---|---| +| USB 安裝隨身碟根目錄 | `autounattend.xml` | +| ISO `sources\` 目錄 | `autounattend.xml` | +| DISM 離線注入已掛載映像 | 任意名稱,用 `/Apply-Unattend:` 指定 | + +--- + +## 驗證工具 + +- **Windows SIM**(Windows System Image Manager,Windows ADK 內含)— 視覺化編輯、驗證、自動產生 Base64 密碼。 +- **VM 試跑**(Hyper-V / VirtualBox / VMware)— 正式部署前先在 VM 全跑一次。 + +--- + +## 安全性 + +- 本範本密碼為明碼,僅適合內網測試;生產環境請改 Base64 或交由 MDT/SCCM 管理。 +- 部署結束後應刪除殘留的 unattend 檔,例如在 `Setup.ps1` 尾端: + ```powershell + Remove-Item C:\Windows\Panther\unattend.xml -Force -ErrorAction SilentlyContinue + Remove-Item C:\Windows\Panther\Unattend\unattend.xml -Force -ErrorAction SilentlyContinue + ``` + +--- + +## 客製延伸 + +可在既有結構上擴充: + +- 加入網域(`Microsoft-Windows-UnattendedJoin.Identification`) +- 安裝特定軟體(`FirstLogonCommands` 呼叫 winget / choco / MSI) +- 整合 WDS / MDT / SCCM 部署流程 +- 多硬碟或 BIOS/MBR 分割配置 diff --git a/SUMMARY.md b/SUMMARY.md new file mode 100644 index 0000000..f8dc714 --- /dev/null +++ b/SUMMARY.md @@ -0,0 +1,94 @@ +# SUMMARY — 這份 unattend.xml 是怎麼長出來的 + +## 為什麼需要它 + +手動裝一台 Windows 是這樣的:按「下一步」、選語系、接受 EULA、分割磁碟、填序號、建帳號、略過 OOBE 一堆隱私問題、登入後開 PowerShell 裝軟體。一台大約 20–30 分鐘,十台就是半天。**而且每次點的選項還不一定一樣。** + +部署這件事的本質是:**把「一次性的人工操作」變成「可重複的檔案」。** + +Windows 給的答案叫 **Answer File**(回應檔,通常是 `unattend.xml`)。開機時 Setup 會去讀這份 XML,把原本需要人類回答的問題一題一題自己答完。 + +--- + +## 設計的三條主線 + +這份 `unattend.xml` 不是隨便把欄位湊齊,而是圍繞三個目標組出來的: + +### 1. 零互動(Zero Touch) + +從 USB 開機到桌面出現,**中間不應該有任何畫面需要鍵盤滑鼠**。 + +為了做到這件事,檔案裡有一連串「否決畫面」的開關: + +- `HideEULAPage` / `HideOEMRegistrationScreen` / `HideOnlineAccountScreens` / `HideWirelessSetupInOOBE` — 把 OOBE 那些煩人的頁面全部隱藏 +- `SkipMachineOOBE` / `SkipUserOOBE` — 機器層與使用者層的 OOBE 都略過 +- `AcceptEula=true` — 安裝時的授權合約預先接受 +- `WillShowUI=OnError` on `ProductKey` — 序號正確就不跳視窗,錯了才問 + +這些不是可有可無的選項,而是「零互動」這個目標的具體落實。 + +### 2. 確定性(Deterministic) + +同一份 `unattend.xml` 套上去,結果應該一樣。 + +- **磁碟分割是硬寫的**:清空 Disk 0 → EFI 500 MB → MSR 128 MB → 剩下全給 Windows。不讓 Setup 自己猜,不處理遷移場景。 +- **語系/時區是硬寫的**:`zh-TW` + `Taipei Standard Time`。不依賴 OEM image 預設。 +- **唯一的例外是電腦名稱**:`PC-%RAND:5%` 刻意引入隨機,因為「確定性」遇到「多台部署不可重名」時要讓路給後者。 + +這是一個取捨:確定性優先,但在會造成衝突的地方(主機名)讓步。 + +### 3. 交棒到腳本(Hand-off to Scripts) + +XML 能做的事有上限。超過這條線(裝軟體、設 Registry、拉 Git repo、裝驅動)就不該硬塞 XML,應該交給 PowerShell。 + +`FirstLogonCommands` 就是交棒點: + +``` +Order 1 → Setup.ps1 (所有「後續設定」都塞這裡) +Order 2 → net accounts (一行搞定的雜事直接 cmd) +Order 3 → shutdown /r (重開機收尾) +``` + +這讓 `unattend.xml` 保持「只負責 Windows 本身的安裝」,其他事情外包給腳本。職責分離之後,改軟體清單不需要動 XML,改部署流程也不需要動 Setup 邏輯。 + +--- + +## 為什麼分成三個 Pass + +Windows Setup 有七個 pass,本檔只用三個。不是偷懶,是**三個 pass 對應三個時機**,各自只能做某些事: + +| Pass | 時機 | 此時系統長什麼樣 | 只能在這裡做的事 | +|---|---|---|---| +| `windowsPE` | 從 USB 開機、Windows 還沒裝 | 記憶體中的迷你作業系統 | 磁碟分割、選要裝哪個映像、產品序號 | +| `specialize` | 映像展開完、第一次開機前 | C:\ 已存在但沒有使用者 | 電腦名稱、加網域、硬體相關 | +| `oobeSystem` | 首次開機、OOBE 跑起來時 | 完整 Windows、等使用者建帳號 | 建本機帳號、AutoLogon、FirstLogonCommands | + +**每個欄位都有「必須」出現的 pass,放錯地方 Windows 就不讀。** 語系要在 `windowsPE` 設(給 WinPE 用)也要在 `oobeSystem` 設(給 OOBE 用)——這就是為什麼 `International-Core` 在檔案裡出現兩次,不是冗餘。 + +--- + +## 妥協的地方 + +幾個「明知道不理想、但為了能動先這樣」的決定: + +| 妥協 | 為什麼這樣 | 正式環境怎麼改 | +|---|---|---| +| **密碼明碼** | 方便第一次測試,看得懂 | 用 Windows SIM 產生 Base64,或交給 MDT/SCCM 管 | +| **本機帳號 + AutoLogon** | 純離線可跑 | 改成 Domain Join + 網域管理員登入 | +| **ProtectYourPC=3** | 略過 OOBE 的隱私頁,預設行為 | 依公司政策調整,或用 GPO 蓋掉 | +| **單一 Disk 0 + 整碟清空** | 對測試 VM 最安全的假設 | 多硬碟環境要加 `DiskID` 判斷邏輯 | +| **`Setup.ps1` 路徑硬寫 C:\Scripts\** | 簡單 | 改從 USB/網路拉,或用 MDT 的 `Applications` 機制 | + +這些不是 bug,是**當前脈絡下的合理起點**。要產品化就對照這張表一個一個升級。 + +--- + +## 對話的起點 + +這份檔案最初是從一個問題開始的: + +> 「透過回應檔案(Answer files,通常檔名為 unattend.xml)來自動化配置 Windows 安裝設定。自動處理像是語系選擇、建立使用者帳號、輸入序號,甚至是執行自定義的腳本。」 + +答案就是上面講的那套設計。剩下的事(產 USB、跑 VM、除錯)都寫在 `QUICKSTART.md`,每個欄位做什麼事寫在 `README.md`。 + +這份 `SUMMARY.md` 只想講一件事:**為什麼這份 XML 長這樣。** 以後如果要改,知道每條線在撐著什麼,就不會拆錯地方。 diff --git a/unattend.xml b/unattend.xml new file mode 100644 index 0000000..85b9759 --- /dev/null +++ b/unattend.xml @@ -0,0 +1,168 @@ + + + + + + + + zh-TW + + 0404:00000404 + zh-TW + zh-TW + zh-TW + + + + + + + 0 + true + + + 1EFI500 + + + 2MSR128 + + + 3Primarytrue + + + + + 11 + FAT32 + + + 23 + NTFSC + + + + + + + + + 03 + + false + + + + + + + XXXXX-XXXXX-XXXXX-XXXXX-XXXXX + OnError + + true + IT Department + YourCompany + + + + + + + + PC-%RAND:5% + Taipei Standard Time + IT Department + YourCompany + + + + + + + 0404:00000404 + zh-TW + zh-TW + zh-TW + + + + + + + true + true + true + true + Work + 3 + true + true + + + + + + + Admin + Administrator + Administrators + + P@ssw0rd! + true</PlainText> + </Password> + </LocalAccount> + </LocalAccounts> + </UserAccounts> + + <AutoLogon> + <Username>Admin</Username> + <Enabled>true</Enabled> + <LogonCount>1</LogonCount> + <Password> + <Value>P@ssw0rd!</Value> + <PlainText>true</PlainText> + </Password> + </AutoLogon> + + <!-- 首次登入執行的自訂腳本 --> + <FirstLogonCommands> + <SynchronousCommand wcm:action="add"> + <Order>1</Order> + <CommandLine>powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\Setup.ps1</CommandLine> + <Description>執行部署後設定腳本</Description> + <RequiresUserInput>false</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <Order>2</Order> + <CommandLine>cmd.exe /c net accounts /maxpwage:unlimited</CommandLine> + <Description>密碼永不過期</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <Order>3</Order> + <CommandLine>shutdown /r /t 5</CommandLine> + <Description>完成後重開機</Description> + </SynchronousCommand> + </FirstLogonCommands> + </component> + </settings> + +</unattend>