###### 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) > 啟用