###### Tags: `autounattend` ``
# Windows作業系統自動化安裝流程
---
## autounattend.xml線上產生器
https://schneegans.de/windows/unattend-generator/
## autounattend.xml
使用AnyBurn編輯ISO映像檔
autounattend.xml直接放ISO映像檔根目錄
### 封裝的程式自動複製到C
封裝路徑: 作業系統ISO\Sources\ \$OEM$ \ \$1\要複製的檔案
### 設定電腦名稱 => 放 unattend-generator 的 Computer name
```
$adapters = Get-NetAdapter | Where-Object { $_.Status -eq 'Up' }
foreach ($adapter in $adapters) {
$addr = Get-NetIPAddress -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue |
Select-Object -First 1 -ExpandProperty IPv4Address
if ($addr) {
$octets = $addr.Split('.')
# 格式化為三位數,前面補零
$part1 = "{0:D3}" -f [int]$octets[-2]
$part2 = "{0:D3}" -f [int]$octets[-1]
"user-$part1$part2"
return
}
}
Write-Warning "Could not determine IP address."
```
### IP自動設定 => 放 unattend-generator 的 System scripts
```ps1=
param (
[string]$ConfigFile = "C:\CDC\Apps\cdc_ip_list.json",
[string]$LogFile = "C:\CDC\ip_setup.log"
)
# === 紀錄 Log ===
function Write-Log {
param ([string]$Message, [string]$Level = "INFO")
$time = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
$logMsg = "[$time][$Level] $Message"
Write-Host $logMsg
Add-Content -Path $LogFile -Value $logMsg
}
# === 確保用系統管理員執行 ===
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()
).IsInRole([Security.Principal.WindowsBuiltinRole] "Administrator")) {
Write-Log "請以系統管理員身份執行此腳本!" "ERROR"
exit 1
}
Write-Log "==== 開始執行 IP 自動設定 ===="
# 讀取 JSON
if (-not (Test-Path $ConfigFile)) {
Write-Log "設定檔不存在: $ConfigFile" "ERROR"
exit 1
}
$ipData = Get-Content $ConfigFile | ConvertFrom-Json
# 取得網卡 (排除虛擬卡)
$InterfaceAlias = (Get-NetAdapter | Where-Object { $_.Status -eq 'Up' -and $_.HardwareInterface -eq $true } |
Select-Object -First 1 -ExpandProperty Name).Trim()
if (-not $InterfaceAlias) {
Write-Log "找不到可用的網卡!" "ERROR"
exit 1
}
Write-Log "目前使用網卡: $InterfaceAlias"
# 取得 MAC
$macAddress = (Get-NetAdapter -Name $InterfaceAlias).MacAddress.Trim()
$normalizedMac = $macAddress.Replace(":", "-").ToUpper()
Write-Log "目前 MAC Address: $normalizedMac"
# 查 IP
$record = $ipData | Where-Object { ($_.PSObject.Properties.Name) -contains $normalizedMac }
if (-not $record) {
Write-Log "未找到對應的 MAC 地址: $normalizedMac" "ERROR"
exit 1
}
$ip = $record.$normalizedMac
# 決定 Gateway
$parts = $ip.Split(".")
$third = [int]$parts[2]
$fourth = [int]$parts[3]
if ($third -eq 6 -and $fourth -le 62) {
$gateway = "192.168.6.62"
} elseif ($third -eq 6 -and $fourth -ge 64) {
$gateway = "192.168.6.126"
} else {
$gateway = "192.168.$third.254"
}
Write-Log "選定 Gateway: $gateway"
# 清理舊設定
Write-Log "移除舊的 IP 與路由..."
Remove-NetIPAddress -InterfaceAlias $InterfaceAlias -AddressFamily IPv4 -Confirm:$false -ErrorAction SilentlyContinue
Remove-NetRoute -InterfaceAlias $InterfaceAlias -Confirm:$false -ErrorAction SilentlyContinue
Set-DnsClientServerAddress -InterfaceAlias $InterfaceAlias -ResetServerAddresses
# 設定新的 IP & Gateway
try {
New-NetIPAddress -InterfaceAlias $InterfaceAlias -IPAddress $ip -PrefixLength 24 -DefaultGateway $gateway -ErrorAction Stop
Write-Log "已設定 IP: $ip, Gateway: $gateway"
} catch {
Write-Log "新增 IP 失敗: $_" "ERROR"
exit 1
}
# 設定 DNS
try {
Set-DnsClientServerAddress -InterfaceAlias $InterfaceAlias -ServerAddresses ("192.168.69.1", "192.168.171.43")
Write-Log "已設定 DNS: 192.168.69.1, 192.168.171.43"
} catch {
Write-Log "設定 DNS 失敗: $_" "ERROR"
exit 1
}
Write-Log "✅ IP 與 DNS 設定完成!"
```
### 不休眠 & 不關閉顯示器 => 放 unattend-generator 的 System scripts
```ps1=
# 啟用 Ultimate Performance
$out = & "$env:windir\System32\powercfg.exe" /DuplicateScheme e9a42b02-d5df-448d-aa00-03f14749eb61
if ($out -match '\s([a-f0-9-]{36})\s') {
$schemeGuid = $Matches[1]
& "$env:windir\System32\powercfg.exe" /SetActive $schemeGuid
# 顯示器永不關閉
& "$env:windir\System32\powercfg.exe" /Change monitor-timeout-ac 0
& "$env:windir\System32\powercfg.exe" /Change monitor-timeout-dc 0
# 系統永不睡眠
& "$env:windir\System32\powercfg.exe" /Change standby-timeout-ac 0
& "$env:windir\System32\powercfg.exe" /Change standby-timeout-dc 0
# 永不休眠
& "$env:windir\System32\powercfg.exe" /Change hibernate-timeout-ac 0
& "$env:windir\System32\powercfg.exe" /Change hibernate-timeout-dc 0
Write-Host "[OK] Ultimate Performance activated, display never off, no sleep, no hibernate."
} else {
Write-Warning "Could not enable Ultimate Performance power scheme."
}
```
### 程式自動安裝 => 放 unattend-generator 的 FirstLogon scripts
```ps1=
# 應用程式安裝路徑
$AppPath = "C:\CDC\Apps"
# ========= 檢查是否以系統管理員執行 =========
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Error "[ERROR] Please run this script as Administrator."
Exit 1
}
# ========= 檢查目錄 =========
if (-not (Test-Path -Path $AppPath)) {
Write-Error "[ERROR] Application path $AppPath does not exist!"
Exit 1
}
Write-Host "[INFO] Found application path: $AppPath"
# ========= 安裝參數表 =========
$InstallerParameters = @{
"cdcIpAutoSet.exe" = $null
"Rapix.exe" = $null
"7zip.exe" = "/S"
"ChromeSetup.exe" = $null
"MODA_ODF.msi" = "/passive"
"ApexOne.msi" = "/qn"
}
# ========= 固定安裝順序 =========
$InstallerFiles = @(
# "cdcIpAutoSet.exe"
"Rapix.exe",
"7zip.exe",
"ChromeSetup.exe", # 自動下載
"MODA_ODF.msi",
"ApexOne.msi"
)
foreach ($FileName in $InstallerFiles) {
# -------- Google Chrome 下載安裝 --------
if ($FileName -eq "ChromeSetup.exe") {
$ChromeUrl = "https://dl.google.com/chrome/install/latest/chrome_installer.exe"
$ChromePath = Join-Path -Path $AppPath -ChildPath "ChromeSetup.exe"
Write-Host "[INFO] Downloading latest Google Chrome..."
Invoke-WebRequest -Uri $ChromeUrl -OutFile $ChromePath -UseBasicParsing
Write-Host "[INFO] Installing Google Chrome (silent mode)..."
$process = Start-Process -FilePath $ChromePath -ArgumentList "/silent","/install" -Wait -PassThru
if ($process.ExitCode -eq 0) {
Write-Host "[OK] Google Chrome installed successfully."
} else {
Write-Warning "[ERROR] Google Chrome installation failed. ExitCode: $($process.ExitCode)"
}
continue
}
# -------- 其他安裝檔 --------
$FullPath = Join-Path -Path $AppPath -ChildPath $FileName
if (-not (Test-Path $FullPath)) {
Write-Warning "[WARN] File $FileName not found. Skipping."
continue
}
$Arguments = $InstallerParameters[$FileName]
Write-Host "[INFO] Installing $FileName with arguments: $Arguments"
if ($FileName -like "*.msi") {
# MSI 安裝
$ArgList = if ($Arguments) { "/i `"$FullPath`" $Arguments" } else { "/i `"$FullPath`"" }
$process = Start-Process -FilePath "msiexec.exe" -ArgumentList $ArgList -Wait -PassThru
} else {
# 其他 exe
if ($Arguments) {
$process = Start-Process -FilePath $FullPath -ArgumentList $Arguments -Wait -PassThru
} else {
$process = Start-Process -FilePath $FullPath -Wait -PassThru
}
}
if ($process.ExitCode -eq 0) {
Write-Host "[OK] $FileName installed successfully."
} else {
Write-Warning "[ERROR] $FileName installation failed. ExitCode: $($process.ExitCode)"
}
}
```
### 執行CMD => 放 FirstLogon scripts
安裝Office要先CD到該資料夾
```
cd /d C:\CDC\Microsoft Office 2024 x64
install.bat
```
### 要設定true, $ OEM $的資料夾才能複製成功
```xml=
<UseConfigurationSet>true</UseConfigurationSet>
```
## Iventoy 網路派送安裝
### 安裝時出現無網卡驅動的解法
[注入模板](https://www.ventoy.net/cn/doc_inject_autorun.html)
[詳細作法](https://forums.ventoy.net/showthread.php?tid=2686):
* 下載 WinInjection.zip 和 DriverIndexer-x64.exe
* 解壓縮 WinInjection.zip
* 將 DriverIndexer-x64.exe 重新命名為 DriverIndexer.exe 並放入 WinInjection \ x\Windows\system32
* 將驅動程式放入WinInjection\ x\drivers 資料夾
* 編輯 Winjection 資料夾編輯VentoyAutoRun.bat
```bat=
@echo off
DriverIndexer.exe load-driver X:\drivers
```
目錄結構如下:
```
X
│ VentoyAutoRun.bat
├─驅動程式
│ └─網卡
│ xxxx.cat
│ xxxx.inf
│ xxxx.sys
└─Windows
└─System32
└─DriverIndexer.exe
```
* 執行 pack.bak 建立 windows_injection.7z
* 將注入檔案設定為 windows_injection.7z
### 本機防火牆設定
輸入規則 > 檔案及印表機共用 (回應要求 - ICMPv4-In) > 啟用