param( $Language = 'zh-CN', $OsVersion = 11, $WindowsProductName = 'Enterprise', $Architecture = 'x64', $DiskId = -1, $PartitionID = -1, $FullName = 'MyPC', $VentoyDriverLetter = '', $ISOPath = '', [switch]$Interactive, [switch]$NotFormat, [switch]$Version ) function GetDefaultFolderPath { return [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::Desktop) } function GetPartitionTypeName { param($GptType, $MbrType, $FileSystem) if ($GptType) { if ($GptType -ieq '{de94bba4-06d1-4d40-a16a-bfd50179d6ac}') { return '微软恢复分区' } elseif ($GptType -ieq '{c12a7328-f81f-11d2-ba4b-00a0c93ec93b}') { return 'EFI 系统分区' } elseif ($GptType -ieq '{e3c9e316-0b5c-4db8-817d-f92df00215ae}') { return '微软保留分区' } elseif ($GptType -ieq '{ebd0a0a2-b9e5-4433-87c0-68b6b72699c7}') { return '基本数据分区' } elseif ($GptType -ieq '{af9b60a0-1431-4f62-bc68-3311714a69ad}') { return '逻辑磁盘管理器元数据分区' } elseif ($GptType -ieq '{af9b60a0-1431-4f62-bc68-3311714a69ad}') { return '逻辑磁盘管理器数据分区' } } if ($MbrType) { if ($MbrType -ieq '1') { return 'FAT12 分区' } elseif ($MbrType -ieq '4') { return 'FAT16 分区' } elseif ($MbrType -ieq '5') { return '扩展分区' } elseif ($MbrType -ieq '6') { return '逻辑分区' } elseif ($MbrType -ieq '7') { return "$FileSystem 分区" } elseif ($MbrType -ieq '12') { return 'FAT32 分区' } } return '未知分区' } function GetCurrentDisk { $CurrentDisks = [ordered]@{} Get-Disk | ForEach-Object { $Partitions = [ordered]@{} $PhydicalDisk = Get-PhysicalDisk -FriendlyName $_.FriendlyName Get-Partition -DiskNumber $_.DiskNumber | ForEach-Object { $Volume = Get-Volume -Partition $_ $PartitionTypeName = GetPartitionTypeName -GptType $_.GptType -MbrType $_.MbrType ` -FileSystem $Volume.FileSystem $Partition = @{ 'Guid' = $_.Guid; # 分区 ID 'PartitionNumber' = $_.PartitionNumber; # 分区编号,值从 1 开始 'DiskNumber' = $_.DiskNumber; # 所属硬盘编号,值从 0 开始 'GptType' = $_.GptType; # 分区类型的 ID 'DriveLetter' = $_.DriveLetter; # 驱动器号,如 C 'FileSystem' = $Volume.FileSystem; # 分区文件系统类型 'FileSystemType' = $Volume.FileSystemType; # 分区文件系统类型 'SizeRemaining' = $Volume.SizeRemaining; # 分区可用空间大小,单位为 Byte 'Size' = $_.Size; # 分区容量,单位为 Byte 'Type' = $_.Type; # GPT 分区类型,System 表示 EFI 分区,Basic 表示基本数据分区,Reserved 表示 MSR 保留分区 'TypeName' = $PartitionTypeName; 'MbrType' = $_.MbrType; # MBR 分区类型的 ID 'IsHidden' = $_.IsHidden; # 是否隐藏分区 'IsBoot' = $_.IsBoot; # 是否启动分区 'IsSystem' = $_.IsSystem; # 是否 EFI 系统分区 'IsActive' = $_.IsActive # 是否活动分区,MBR 才有意义,GPT 无意义 } $Partitions.Add($_.PartitionNumber, $Partition) } $Disk = @{ 'DiskNumber' = $_.DiskNumber; # 硬盘编号,值从 0 开始 'PartitionStyle' = $_.PartitionStyle; # 分区类型,如 GPT 或 MBR 'MediaType' = $PhydicalDisk.MediaType; # 硬盘类型,如 SSD 或 HDD 'OperationalStatus' = $_.OperationalStatus; # 硬盘状态,如 Online 'HealthStatus' = $_.HealthStatus; # 硬盘健康状态,如 Healthy 'BusType' = $_.BusType; # 硬盘接口类型,如 RAID 或 USB 'BootFromDisk' = $_.BootFromDisk; # 是否从该硬盘启动 'FirmwareVersion' = $_.FirmwareVersion; # 硬盘固件版本 'FriendlyName' = $_.FriendlyName; # 硬盘名称 'IsBoot' = $_.IsBoot; # 是否从该硬盘启动 'IsSystem' = $_.IsSystem; # 是否系统盘 'Manufacturer' = $_.Manufacturer; # 硬盘制造商 'Model' = $_.Model; # 硬盘型号 'NumberOfPartitions' = $_.NumberOfPartitions; # 硬盘分区数量 'Size' = $_.Size; # 硬盘容量,单位为 Byte 'AllocatedSize' = $PhydicalDisk.AllocatedSize; # 已分配容量,单位为 Byte 'Partitions' = $Partitions } $CurrentDisks.Add($_.DiskNumber, $Disk) } return $CurrentDisks } function GetSystemDiskId { $CurrentDisks = GetCurrentDisk foreach ($_ in $CurrentDisks.GetEnumerator()) { if ($_.Value['IsBoot']) { return $_.Value['DiskNumber'] } } return 0 } function GetSystemPartitionId { $CurrentDisks = GetCurrentDisk foreach ($_ in $CurrentDisks.GetEnumerator()) { foreach ($__ in $_.Value['Partitions'].GetEnumerator()) { if ($__.Value['IsBoot']) { return $__.Value['PartitionNumber'] } } } return 1 } function FormatSize { param($Size) $Tb = [Math]::Round($Size * 1.0 / 1024 / 1024 / 1024 / 1024, 2) if ($Tb -gt 1) { return "$Tb" + ' TB' } $Gb = [Math]::Round($Size * 1.0 / 1024 / 1024 / 1024, 2) if ($Gb -gt 1) { return "$Gb" + ' GB' } $Mb = [Math]::Round($Size * 1.0 / 1024 / 1024, 2) if ($Mb -gt 1) { return "$Mb" + ' MB' } $Kb = [Math]::Round($Size * 1.0 / 1024, 2) if ($Kb -gt 1) { return "$Kb" + ' KB' } if ($Size -le 0) { return '0 Byte' } return "$Size" + ' Byte' } function ShowLanguageSelect { Write-Host -Object '============================' Write-Host -Object '选择要安装系统的语言,推荐 1' Write-Host -Object '============================' Write-Host -Object '' Write-Host -Object '1: 简体中文 zh-CN' Write-Host -Object '' Write-Host -Object '2: 英文 en-US' while ($true) { Write-Host -Object '' $InputOption = Read-Host -Prompt '请输入选择的序号(默认为 1),按回车键确认' if ($InputOption -ieq '' -or $InputOption -ieq '1') { Write-Host -Object '' return 'zh-CN' } elseif ($InputOption -ieq '2') { Write-Host -Object '' return 'en-US' } else { Write-Host -Object '' Write-Warning -Message '选择无效,请重新输入' } } } function ShowOsVersionSelect { Write-Host -Object '============================' Write-Host -Object '选择要安装系统的版本,推荐 1' Write-Host -Object '============================' Write-Host -Object '' Write-Host -Object '1: Windows 11' Write-Host -Object '' Write-Host -Object '2: Windows 10' while ($true) { Write-Host -Object '' $InputOption = Read-Host -Prompt '请输入选择的序号(默认为 1),按回车键确认' if ($InputOption -ieq '' -or $InputOption -ieq '1') { Write-Host -Object '' return 11 } elseif ($InputOption -ieq '2') { Write-Host -Object '' return 10 } else { Write-Host -Object '' Write-Warning -Message '选择无效,请重新输入' } } } function ShowWindowsProductNameSelect { Write-Host -Object '============================' Write-Host -Object '选择要安装系统的产品,推荐 1' Write-Host -Object '============================' Write-Host -Object '' Write-Host -Object '1: 企业版 Enterprise' Write-Host -Object '' Write-Host -Object '2: 教育版 Education' Write-Host -Object '' Write-Host -Object '3: 专业版 Pro' Write-Host -Object '' Write-Host -Object '4: 专业教育版 Pro Education' Write-Host -Object '' Write-Host -Object '5: 专业工作站版 Pro For Workstations' Write-Host -Object '' Write-Host -Object '6: 其他' while ($true) { Write-Host -Object '' $InputOption = Read-Host -Prompt '请输入选择的序号(默认为 1),按回车键确认' if ($InputOption -ieq '' -or $InputOption -ieq '1') { Write-Host -Object '' return 'Enterprise' } elseif ($InputOption -ieq '2') { Write-Host -Object '' return 'Education' } elseif ($InputOption -ieq '3') { Write-Host -Object '' return 'Pro' } elseif ($InputOption -ieq '4') { Write-Host -Object '' return 'Pro Education' } elseif ($InputOption -ieq '5') { Write-Host -Object '' return 'Pro For Workstations' } elseif ($InputOption -ieq '6') { Write-Host -Object '' return '' } else { Write-Host -Object '' Write-Warning -Message '选择无效,请重新输入' } } } function ShowArchitectureSelect { param($OsVersion) if ($OsVersion -eq 11) { return 'x64' } Write-Host -Object '============================' Write-Host -Object '选择要安装系统的架构,推荐 1' Write-Host -Object '============================' Write-Host -Object '' Write-Host -Object '1: 64 位系统 x64' Write-Host -Object '' Write-Host -Object '2: 32 位系统 x86' while ($true) { Write-Host -Object '' $InputOption = Read-Host -Prompt '请输入选择的序号(默认为 1),按回车键确认' if ($InputOption -ieq '' -or $InputOption -ieq '1') { Write-Host -Object '' return 'x64' } elseif ($InputOption -ieq '2') { Write-Host -Object '' return 'x86' } else { Write-Host -Object '' Write-Warning -Message '选择无效,请重新输入' } } } function ShowDiskIdSelect { $SystemDiskId = GetSystemDiskId $CurrentDisks = GetCurrentDisk Write-Host -Object '================================================' Write-Host -Object "选择要安装系统的硬盘编号,推荐当前系统所在硬盘 $SystemDiskId" Write-Host -Object '================================================' Write-Host -Object '' Write-Host -Object '当前系统识别到的硬盘如下:红色字体的硬盘为当前系统所在硬盘,红色字体的分区为当前系统所在分区' $CurrentDisks.GetEnumerator() | ForEach-Object { $msg = '硬盘编号: ' + $_.Value['DiskNumber'] + ', 硬盘类型: ' + $_.Value['MediaType'] + ', 接口类型: ' ` + $_.Value['BusType'] + ', 分区类型: ' + $_.Value['PartitionStyle'] + ', 硬盘容量: ' ` + (FormatSize -Size $_.Value['Size']) + ', 硬盘名称: ' + $_.Value['FriendlyName'] Write-Host -Object '' if ($_.Value['IsBoot']) { Write-Host -Object $msg -ForegroundColor Red } else { Write-Host -Object $msg } $_.Value['Partitions'].GetEnumerator() | ForEach-Object { $msg = ' |- 分区编号: ' + $_.Value['PartitionNumber'] + ', 驱动器: ' + $_.Value['DriveLetter'] ` + ', 是否隐藏: ' + $_.Value['IsHidden'] + ', 文件系统: ' + $_.Value['FileSystem'] + ', 类型: ' ` + $_.Value['TypeName'] + ', 可用空间: ' + (FormatSize -Size $_.Value['SizeRemaining']) + ', 容量: ' ` + ( FormatSize -Size $_.Value['Size']) Write-Host -Object ' |' if ($_.Value['IsBoot']) { Write-Host -Object $msg -ForegroundColor Red } else { Write-Host -Object $msg } } } while ($true) { Write-Host -Object '' try { [System.Int32]$InputOption = Read-Host ` -Prompt "请输入选择的硬盘编号(硬盘编号从 0 开始,默认为 $SystemDiskId),按回车键确认" if ($InputOption -ge 0) { Write-Host -Object '' return $InputOption } else { Write-Host -Object '' Write-Warning -Message '输入无效,请重新输入' } } catch { Write-Host -Object '' Write-Warning -Message '输入无效,请重新输入' } } } function ShowWipeDiskSelect { param($DiskId) $CurrentDisks = GetCurrentDisk $SelectDisk = $CurrentDisks[$DiskId] $DefaultWipe = $false $DefalultSelect = 2 if ($SelectDisk -and $SelectDisk['PartitionStyle'] -ine 'GPT') { Write-Host -Object '======================================================================' Write-Host -Object '选择是否对所选硬盘进行 GPT 分区,所选系统只支持 GPT 分区的硬盘,推荐 2' Write-Host -Object '======================================================================' $DefaultWipe = $true $DefalultSelect = 2 } else { Write-Host -Object '======================================================================' Write-Host -Object '选择是否对所选硬盘进行 GPT 分区,所选系统只支持 GPT 分区的硬盘,推荐 1' Write-Host -Object '======================================================================' $DefaultWipe = $false $DefalultSelect = 1 } Write-Host -Object '' Write-Host -Object '1: 否' Write-Host -Object '' Write-Host -Object '2: 是,注意:安装系统时会清除所选硬盘的数据,请及时备份所选硬盘的数据' -ForegroundColor Red while ($true) { Write-Host -Object '' $InputOption = Read-Host -Prompt "请输入选择的序号(默认为 $DefalultSelect),按回车键确认" if ($InputOption -ieq '') { Write-Host -Object '' return $DefaultWipe } elseif ($InputOption -ieq '1') { Write-Host -Object '' return $false } elseif ($InputOption -ieq '2') { Write-Host -Object '' return $true } else { Write-Host -Object '' Write-Warning -Message '选择无效,请重新输入' } } } function ShowNewPartition { param($CreatePartitionInfo) Write-Host -Object '所选硬盘重新分区如下:红色字体的分区为系统安装分区' Write-Host -Object '' $CreatePartitionInfo.GetEnumerator() | ForEach-Object { $VolumeSize = '硬盘剩余所有空间' if (!$_.Value['Extend']) { $VolumeSize = FormatSize -Size $($_.Value['Size'] * 1024 * 1024) } $msg = '分区编号: ' + $_.Value['Order'] + ', 是否隐藏: ' + $_.Value['IsHidden'] + ', 文件系统: ' ` + $_.Value['FileSystem'] + ', 类型: ' + $_.Value['TypeName'] + ', 容量: ' + $VolumeSize if ($_.Value['IsBoot']) { Write-Host -Object $msg -ForegroundColor Red } else { Write-Host -Object $msg } Write-Host -Object '' } } function ShowAddNewPartition { while ($true) { $InputOption = Read-Host -Prompt '是否增加新分区(0: 否, 1: 是),按回车键确认' Write-Host -Object '' if ($InputOption -ieq '0') { return $false } elseif ($InputOption -ieq '1') { return $true } else { Write-Warning -Message '输入无效,请重新输入' Write-Host -Object '' } } } function ShowIsBoot { param($CreatePartitionInfo) Write-Host -Object '================================================' Write-Host -Object '选择要安装系统的分区编号,类型必须为基本数据分区' Write-Host -Object '================================================' Write-Host -Object '' ShowNewPartition -CreatePartitionInfo $CreatePartitionInfo while ($true) { $InputOption = Read-Host -Prompt '请输入选择的分区编号(分区编号从 1 开始,类型必须为基本数据分区),按回车键确认' $SelectPartition = $CreatePartitionInfo[$InputOption] if ($SelectPartition) { if ($SelectPartition['Type'] -ieq 'Primary') { Write-Host -Object '' $SelectPartition['IsBoot'] = $true $Script:PartitionID = $SelectPartition['Order'] return } else { Write-Host -Object '' Write-Warning -Message '所选分区非基本数据分区,只能选择基本数据分区,请重新输入' Write-Host -Object '' } } else { Write-Host -Object '' Write-Warning -Message '所选分区不存在,请重新输入' Write-Host -Object '' } } } function ShowCreatePartition { $CreatePartitionInfo = [ordered]@{ '1' = @{ 'Order' = 1; 'Size' = 300; 'Type' = 'EFI'; 'TypeName' = 'EFI 分区'; 'FileSystem' = 'FAT32'; 'Extend' = $false; 'IsHidden' = $true; 'IsBoot' = $false }; '2' = @{ 'Order' = 2; 'Size' = 200; 'Type' = 'MSR'; 'TypeName' = '微软保留分区'; 'FileSystem' = ''; 'Extend' = $false; 'IsHidden' = $true; 'IsBoot' = $false } } Write-Host -Object '==========' Write-Host -Object '创建新分区' Write-Host -Object '==========' Write-Host -Object '' $PartitionNumber = 2 ShowNewPartition -CreatePartitionInfo $CreatePartitionInfo while ($true) { try { $PartitionNumber = $PartitionNumber + 1 [System.Int32]$InputOption = Read-Host ` -Prompt "输入第 $PartitionNumber 个分区的大小,0 表示占用硬盘所有剩余空间(默认为 0),单位为 MB,按回车键确认" if ($InputOption -eq 0) { Write-Host -Object '' $CreatePartitionInfo.Add([System.String]$PartitionNumber, @{ 'Order' = $PartitionNumber; 'Size' = 0; 'Type' = 'Primary'; 'TypeName' = '基本数据分区'; 'FileSystem' = 'NTFS'; 'Extend' = $true; 'IsHidden' = $false; 'IsBoot' = $false }) ShowNewPartition -CreatePartitionInfo $CreatePartitionInfo break } elseif ($InputOption -gt 0) { Write-Host -Object '' $CreatePartitionInfo.Add([System.String]$PartitionNumber, @{ 'Order' = $PartitionNumber; 'Size' = $InputOption; 'Type' = 'Primary'; 'TypeName' = '基本数据分区'; 'FileSystem' = 'NTFS'; 'Extend' = $false; 'IsHidden' = $false; 'IsBoot' = $false }) ShowNewPartition -CreatePartitionInfo $CreatePartitionInfo } else { $PartitionNumber = $PartitionNumber - 1 Write-Host -Object '' Write-Warning -Message '输入无效,请重新输入' Write-Host -Object '' continue } $ShowAddNewPartition = ShowAddNewPartition if (!$ShowAddNewPartition) { $CreatePartitionInfo["$PartitionNumber"]['Extend'] = $true break } } catch { $PartitionNumber = $PartitionNumber - 1 Write-Host -Object '' Write-Warning -Message '输入无效,请重新输入' Write-Host -Object '' } } ShowIsBoot -CreatePartitionInfo $CreatePartitionInfo ShowNewPartition -CreatePartitionInfo $CreatePartitionInfo return $CreatePartitionInfo } function ShowPartitionIdSelect { param($DiskId) $DefalultSelect = GetSystemPartitionId $CurrentDisks = GetCurrentDisk $SelectDisk = $CurrentDisks[$DiskId] if ($SelectDisk) { Write-Host -Object '================================================' Write-Host -Object "选择要安装系统的分区编号,推荐当前系统所在分区 $DefalultSelect" Write-Host -Object '================================================' Write-Host -Object '' Write-Host -Object '所选硬盘的分区如下:红色字体的分区为当前系统所在分区' $SelectDisk['Partitions'].GetEnumerator() | ForEach-Object { $msg = '分区编号: ' + $_.Value['PartitionNumber'] + ', 驱动器: ' + $_.Value['DriveLetter'] + ', 是否隐藏: ' ` + $_.Value['IsHidden'] + ', 文件系统: ' + $_.Value['FileSystem'] + ', 类型: ' + $_.Value['TypeName'] ` + ', 可用空间: ' + (FormatSize -Size $_.Value['SizeRemaining']) + ', 容量: ' ` + (FormatSize -Size $_.Value['Size']) Write-Host -Object '' if ($_.Value['IsBoot']) { Write-Host -Object $msg -ForegroundColor Red } else { Write-Host -Object $msg } } } else { Write-Host -Object '================================' Write-Host -Object "选择要安装系统的分区编号,推荐 $DefalultSelect" Write-Host -Object '================================' } while ($true) { Write-Host -Object '' $InputOption = Read-Host -Prompt "请输入选择的分区编号(分区编号从 1 开始,默认为 $DefalultSelect),按回车键确认" if ($InputOption -ieq '') { Write-Host -Object '' return $DefalultSelect } try { [System.Int32]$InputOption1 = [System.Int32]$InputOption if ($InputOption1 -eq 0) { Write-Host -Object '' Write-Warning -Message '输入无效,请重新输入' continue } if ($InputOption1 -ge 1) { Write-Host -Object '' return $InputOption1 } else { Write-Host -Object '' Write-Warning -Message '输入无效,请重新输入' } } catch { Write-Host -Object '' Write-Warning -Message '输入无效,请重新输入' } } } function ShowFomatSelect { Write-Host -Object '================================' Write-Host -Object '选择是否对所选分区格式化,推荐 2' Write-Host -Object '================================' Write-Host -Object '' Write-Host -Object '1: 否' Write-Host -Object '' Write-Host -Object '2: 是,注意:安装系统时会清除所选分区的数据,请及时备份所选分区的数据' -ForegroundColor Red while ($true) { Write-Host -Object '' $InputOption = Read-Host -Prompt '请输入选择的序号(默认为 2),按回车键确认' if ($InputOption -ieq '' -or $InputOption -ieq '2') { Write-Host -Object '' return $true } elseif ($InputOption -ieq '1') { Write-Host -Object '' return $false } else { Write-Host -Object '' Write-Warning -Message '选择无效,请重新输入' } } } function ShowNameInput { Write-Host -Object '==================================================' Write-Host -Object '输入系统安装后的登录账号名,账号名建议符合如下要求' Write-Host -Object '==================================================' Write-Host -Object '' Write-Host -Object '1: 推荐英文字母或数字的组合,尽量不使用特殊字符' Write-Host -Object '' Write-Host -Object '2: 尽量不使用中文,防止某些应用软件不支持中文而无法使用' Write-Host -Object '' $InputOption = Read-Host -Prompt '请输入登录账号名(默认为 MyPC),按回车键确认' if ($InputOption -ieq '') { Write-Host -Object '' return 'MyPC' } else { Write-Host -Object '' return $InputOption } } function ShowVentoyDriverLetterSelect { $CurrentDisks = GetCurrentDisk Write-Host -Object '===============================' Write-Host -Object '输入已安装 Ventoy 的 U 盘驱动器' Write-Host -Object '===============================' Write-Host -Object '' Write-Host -Object '当前系统识别到的驱动器如下:' $CurrentDisks.GetEnumerator() | ForEach-Object { $msg = '硬盘类型: ' + $_.Value['MediaType'] + ', 接口类型: ' + $_.Value['BusType'] + ', 分区类型: ' ` + $_.Value['PartitionStyle'] + ', 硬盘容量: ' + (FormatSize -Size $_.Value['Size']) + ', 硬盘名称: ' ` + $_.Value['FriendlyName'] Write-Host -Object '' Write-Host -Object $msg $_.Value['Partitions'].GetEnumerator() | ForEach-Object { if ($_.Value['DriveLetter']) { $msg = ' |- 驱动器: ' + $_.Value['DriveLetter'] + ', 文件系统: ' + $_.Value['FileSystem'] ` + ', 可用空间: ' + (FormatSize -Size $_.Value['SizeRemaining']) + ', 容量: ' ` + (FormatSize -Size $_.Value['Size']) Write-Host -Object ' |' Write-Host -Object $msg } } } while ($true) { Write-Host -Object '' $InputOption = Read-Host ` -Prompt '请输入已安装 Ventoy 的 U 盘驱动器(0 表示将应答文件保存到当前用户的桌面上),按回车键确认' if ($InputOption -ieq '') { Write-Host -Object '' Write-Warning -Message '选择无效,请重新输入' } elseif ($InputOption -ieq '0') { Write-Host -Object '' return '' } elseif (Test-Path -Path $InputOption -PathType Container) { Write-Host -Object '' return $InputOption } elseif (Test-Path -Path $($InputOption + ':\') -PathType Container) { Write-Host -Object '' return $($InputOption + ':\') } else { Write-Host -Object '' Write-Warning -Message '驱动器不存在,请重新输入' } } } function ShowGetISOPath { param($Path) Write-Host -Object '===============================' Write-Host -Object '选择使用应答文件的 ISO 镜像文件' Write-Host -Object '===============================' Write-Host -Object '' Write-Host -Object '搜索 ISO 镜像文件中......' $ISOFiles = [ordered]@{} $Index = 0; try { Get-ChildItem -Path $Path -Include '*.iso' -Recurse -File | ForEach-Object { $Index = $Index + 1 $ISOFiles.Add([System.String]$Index, $_.FullName) } } catch { $msg = $Path + ' 无权限' Write-Warning -Message $msg } if ($ISOFiles.Count -gt 0) { Write-Host -Object '' Write-Host -Object '搜索到的镜像文件如下:' $ISOFiles.GetEnumerator() | ForEach-Object { Write-Host -Object '' $msg = '镜像文件序号: ' + $_.Key + ', 镜像文件路径: ' + $_.Value Write-Host -Object $msg } while ($true) { Write-Host -Object '' $InputOption = Read-Host -Prompt '请输入使用应答文件的 ISO 镜像文件序号,按回车键确认' $ISOFile = $ISOFiles[$InputOption] if ($ISOFile) { Write-Host -Object '' return $ISOFile } else { Write-Host -Object '' Write-Warning -Message '镜像文件序号不存在,请重新输入' } } } else { Write-Host -Object '' Write-Host -Object '未搜索到 ISO 镜像文件' Write-Host -Object '' return '' } } function UpdateVentoyConfig { param( $ISOPath, $UnattendPath, $VentoyConfigParentPath ) if (!$ISOPath) { return } if (!$UnattendPath) { return } if (!$VentoyConfigParentPath) { return } $ISOPath = Split-Path -Path $ISOPath -NoQualifier $ISOPath = $ISOPath.Replace('\', '/') $UnattendPath = Split-Path -Path $UnattendPath -NoQualifier $UnattendPath = $UnattendPath.Replace('\', '/') $VentoyConfigJsonPath = Join-Path -Path $VentoyConfigParentPath -ChildPath 'ventoy.json' $JSONContent = $null if (Test-Path -Path $VentoyConfigJsonPath -PathType Leaf) { try { $JSONContent = Get-Content -Path $VentoyConfigJsonPath | ConvertFrom-Json } catch { $msg = $VentoyConfigJsonPath + ' 解析失败' Write-Warning -Message $msg } } if (!$JSONContent -or !($JSONContent -is [PSCustomObject])) { $JSONContent = [PSCustomObject]@{ 'control' = @(@{ 'VTOY_WIN11_BYPASS_CHECK' = '1' }); 'auto_install' = @(@{ 'image' = $ISOPath; 'template' = $UnattendPath }) } $JSONString = $JSONContent | ConvertTo-Json $Utf8NoBomEncoding = New-Object -TypeName System.Text.UTF8Encoding -ArgumentList $false [System.IO.File]::WriteAllLines($VentoyConfigJsonPath, $JSONString, $Utf8NoBomEncoding) return } $Controls = $JSONContent.'control' if ($null -eq $Controls -or !($Controls -is [System.Array])) { Add-Member -InputObject $JSONContent -Force ` -NotePropertyMembers @{ 'control' = @(@{ 'VTOY_WIN11_BYPASS_CHECK' = '1' }) } } else { $AddFlag = $false foreach ($Control in $Controls) { if ($null -eq $Control) { $AddFlag = $true Add-Member -InputObject $Control -Force -NotePropertyMembers @{ 'VTOY_WIN11_BYPASS_CHECK' = '1' } break } $Check = $Control.'VTOY_WIN11_BYPASS_CHECK' if ($null -eq $Check) { continue } $AddFlag = $true Add-Member -InputObject $Control -Force -NotePropertyMembers @{ 'VTOY_WIN11_BYPASS_CHECK' = '1' } break } if (!$AddFlag) { $Controls += [PSCustomObject]@{ 'VTOY_WIN11_BYPASS_CHECK' = '1' } $JSONContent.'control' = $Controls } } $Installs = $JSONContent.'auto_install' if ($null -eq $Installs -or !($Installs -is [System.Array])) { Add-Member -InputObject $JSONContent -Force ` -NotePropertyMembers @{ 'auto_install' = @(@{ 'image' = $ISOPath; 'template' = $UnattendPath }) } } else { $AddFlag = $false foreach ($Install in $Installs) { if ($null -eq $Install) { Add-Member -InputObject $Install -Force ` -NotePropertyMembers @{ 'image' = $ISOPath; 'template' = $UnattendPath } $AddFlag = $true break } $Image = $Install.'image' if ($null -eq $Image) { Add-Member -InputObject $Install -Force ` -NotePropertyMembers @{ 'image' = $ISOPath; 'template' = $UnattendPath } $AddFlag = $true break } if ($Image -ne $ISOPath) { continue } Add-Member -InputObject $Install -Force ` -NotePropertyMembers @{ 'image' = $ISOPath; 'template' = $UnattendPath } $AddFlag = $true break } if (!$AddFlag) { $Installs += [PSCustomObject]@{ 'image' = $ISOPath; 'template' = $UnattendPath } $JSONContent.'auto_install' = $Installs } } $JSONString = $JSONContent | ConvertTo-Json $Utf8NoBomEncoding = New-Object -TypeName System.Text.UTF8Encoding -ArgumentList $false [System.IO.File]::WriteAllLines($VentoyConfigJsonPath, $JSONString, $Utf8NoBomEncoding) } $VersionInfo = 'v2022.6.11' if ($Version) { return $VersionInfo } Clear-Host $PSDefaultParameterValues['*:Encoding'] = 'utf8' $Host.UI.RawUI.WindowTitle = 'Windows 应答文件生成' Set-Location -Path $PSScriptRoot Write-Host -Object "=====> Windows 系统自动安装应答文件生成 $VersionInfo <=====" Write-Host -Object '' $WipeDisk = $false $Token = '31bf3856ad364e35' $WindowsProduct = [ordered]@{ 'Enterprise' = @{ 'CN' = '企业版'; 'US' = 'Enterprise'; 'NoSpaceName' = 'Enterprise'; 'gvlk' = 'NPPR9-FWDCX-D2C8J-H872K-2YT43' }; 'Education' = @{ 'CN' = '教育版'; 'US' = 'Education'; 'NoSpaceName' = 'Education'; 'gvlk' = '6TP4R-GNPTD-KYYHQ-7B7DP-J447Y' }; 'Pro' = @{ 'CN' = '专业版'; 'US' = 'Pro'; 'NoSpaceName' = 'Pro'; 'gvlk' = 'W269N-WFGWX-YVC9B-4J6C9-T83GX' }; 'Pro Education' = @{ 'CN' = '专业教育版'; 'US' = 'Pro Education'; 'NoSpaceName' = 'Pro_Education'; 'gvlk' = '6TP4R-GNPTD-KYYHQ-7B7DP-J447Y' }; 'Pro For Workstations' = @{ 'CN' = '专业工作站版'; 'US' = 'Pro For Workstations'; 'NoSpaceName' = 'Pro_For_Workstations'; 'gvlk' = 'NRG8B-VKK3Q-CXVCJ-9G2XF-6Q84J' } } $CurrentDisks = GetCurrentDisk if ($Interactive) { $Language = ShowLanguageSelect $OsVersion = ShowOsVersionSelect $WindowsProductName = ShowWindowsProductNameSelect $Architecture = ShowArchitectureSelect -OsVersion $OsVersion $DiskId = ShowDiskIdSelect $WipeDisk = ShowWipeDiskSelect -DiskId $DiskId if ($WipeDisk) { $CreatePartitionInfo = ShowCreatePartition } else { $PartitionID = ShowPartitionIdSelect -DiskId $DiskId $NotFormat = !$(ShowFomatSelect) } $FullName = ShowNameInput $VentoyDriverLetter = ShowVentoyDriverLetterSelect if ($VentoyDriverLetter) { $ISOPath = ShowGetISOPath -Path $VentoyDriverLetter } } if ($Language -ine 'zh-CN' -and $Language -ine 'en-US') { Write-Warning -Message '参数 Language 只支持 zh-CN (简体中文), en-US (英文)' [System.Environment]::Exit(0) } if ($Language -ieq 'zh-CN') { $Language = 'zh-CN' } elseif ($Language -ieq 'en-US') { $Language = 'en-US' } if ($OsVersion -ne 10 -and $OsVersion -ne 11) { Write-Warning -Message '参数 OsVersion 只支持 10 (Windows 10), 11 (Windows 11)' [System.Environment]::Exit(0) } if ($WindowsProductName -and !$WindowsProduct.Contains($WindowsProductName)) { $WindowsProductNameArray = @($WindowsProduct.GetEnumerator() | ForEach-Object { $_.Value['US'] + ' (' + $_.Value['CN'] + ')' }) $AllSupportProductName = [string]::join(', ', $WindowsProductNameArray) Write-Warning -Message "参数 WindowsProductName 只支持 $AllSupportProductName" [System.Environment]::Exit(0) } if ($OsVersion -eq 10) { if ($Architecture -ne 'x64' -and $Architecture -ne 'x86') { Write-Warning -Message '参数 OsVersion 为 Windows 10 时,参数 Architecture 只支持 x64 (64 位系统), x86 (32 位系统)' [System.Environment]::Exit(0) } } if ($OsVersion -eq 11) { if ($Architecture -ine 'x64') { Write-Warning -Message '参数 OsVersion 为 Windows 11 时,参数 Architecture 只支持 x64 (64 位系统)' [System.Environment]::Exit(0) } } $ArchitectureName = 'amd64' if ($Architecture -eq 'x86') { $ArchitectureName = 'x86' } if ($DiskId -eq -1) { $DiskId = GetSystemDiskId } if ($PartitionID -eq -1) { $PartitionID = GetSystemPartitionId } if ('' -ieq $VentoyDriverLetter) { $ParentPath = GetDefaultFolderPath } else { $ParentPath = $VentoyDriverLetter if ($ISOPath) { $Letter1 = Split-Path -Path $ISOPath -Qualifier $Letter2 = Split-Path -Path $ISOPath -Qualifier if ($Letter1 -ine $Letter2) { Write-Warning -Message '参数 ISOPath 指定的路径必须和参数 VentoyDriverLetter 指定的驱动器属于同一个驱动器' [System.Environment]::Exit(0) } } } $VentoyConfigParentPath = Join-Path -Path $ParentPath -ChildPath 'ventoy' if (!$(Test-Path -Path $VentoyConfigParentPath -PathType Container)) { New-Item -Path $VentoyConfigParentPath -ItemType Directory -Force Write-Host -Object '' } $VentoyConfigScriptPath = Join-Path -Path $VentoyConfigParentPath -ChildPath 'script' if (!$(Test-Path -Path $VentoyConfigScriptPath -PathType Container)) { New-Item -Path $VentoyConfigScriptPath -ItemType Directory -Force Write-Host -Object '' } $ProductInfo = @{} if ('' -ieq $WindowsProductName) { $UnattendPath = $VentoyConfigScriptPath + '\Unattend_Windows_' + $OsVersion + '_' + $Architecture + '_' ` + $Language + '_' + $FullName + '.xml' } else { $ProductInfo = $WindowsProduct[$WindowsProductName] $NoSpaceName = $ProductInfo['NoSpaceName'] $UnattendPath = $VentoyConfigScriptPath + '\Unattend_Windows_' + $OsVersion + '_' + $NoSpaceName + '_' ` + $Architecture + '_' + $Language + '_' + $FullName + '.xml' } UpdateVentoyConfig -ISOPath $ISOPath -UnattendPath $UnattendPath -VentoyConfigParentPath $VentoyConfigParentPath if (Test-Path -Path $UnattendPath -PathType Leaf) { Remove-Item -Path $UnattendPath -Force } Add-Content -Path $UnattendPath -Value '' Add-Content -Path $UnattendPath -Value '' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value (" ") Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value " $Language" Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value " $Language" Add-Content -Path $UnattendPath -Value " $Language" Add-Content -Path $UnattendPath -Value " $Language" Add-Content -Path $UnattendPath -Value " $Language" Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value '' Add-Content -Path $UnattendPath -Value (" ") Add-Content -Path $UnattendPath -Value ' false' Add-Content -Path $UnattendPath -Value '' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' true' if ($FullName) { Add-Content -Path $UnattendPath -Value " $FullName" } if ($WindowsProductName) { $key = $ProductInfo['gvlk'] Add-Content -Path $UnattendPath -Value " $key" } Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value '' if ($WipeDisk) { Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value " $DiskId" Add-Content -Path $UnattendPath -Value '' Add-Content -Path $UnattendPath -Value ' true' Add-Content -Path $UnattendPath -Value '' Add-Content -Path $UnattendPath -Value ' ' $CreatePartitionInfo.GetEnumerator() | ForEach-Object { Add-Content -Path $UnattendPath -Value ' ' if ($_.Value['Extend']) { Add-Content -Path $UnattendPath -Value ' true' } else { $Size = $_.Value['Size'] Add-Content -Path $UnattendPath -Value " $Size" } $Order = $_.Value['Order'] Add-Content -Path $UnattendPath -Value " $Order" $Type = $_.Value['Type'] Add-Content -Path $UnattendPath -Value " $Type" Add-Content -Path $UnattendPath -Value ' ' } Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value '' Add-Content -Path $UnattendPath -Value ' ' $CreatePartitionInfo.GetEnumerator() | ForEach-Object { Add-Content -Path $UnattendPath -Value ' ' $Format = $_.Value['FileSystem'] if ($Format) { Add-Content -Path $UnattendPath -Value " $Format" } $Order = $_.Value['Order'] Add-Content -Path $UnattendPath -Value " $Order" Add-Content -Path $UnattendPath -Value " $Order" $Type = $_.Value['Type'] Add-Content -Path $UnattendPath -Value " $Type" Add-Content -Path $UnattendPath -Value ' ' } Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value '' } elseif (!$NotFormat) { Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value " $DiskId" Add-Content -Path $UnattendPath -Value '' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' NTFS' Add-Content -Path $UnattendPath -Value " $PartitionID" Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value '' } Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' if ($WindowsProductName) { if ($Language -ieq 'zh-CN') { $ImageName = 'Windows ' + $OsVersion + ' ' + $ProductInfo['CN'] } else { $ImageName = 'Windows ' + $OsVersion + ' ' + $ProductInfo['US'] } Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' /IMAGE/NAME' Add-Content -Path $UnattendPath -Value " $ImageName" Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value '' } Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value " $DiskId" Add-Content -Path $UnattendPath -Value " $PartitionID" Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value '' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value (" ") if ($FullName) { Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value " $FullName" Add-Content -Path $UnattendPath -Value ' Administrators' Add-Content -Path $UnattendPath -Value " $FullName" Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value '' } Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' true' Add-Content -Path $UnattendPath -Value ' true' Add-Content -Path $UnattendPath -Value ' true' Add-Content -Path $UnattendPath -Value ' true' Add-Content -Path $UnattendPath -Value ' true' Add-Content -Path $UnattendPath -Value ' 3' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value ' ' Add-Content -Path $UnattendPath -Value '' Write-Host -Object ('生成的应答文件位置: ' + $UnattendPath) Write-Host -Object '' Read-Host -Prompt '按回车键关闭此窗口'