diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f97022 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target/ \ No newline at end of file diff --git a/README.md b/README.md index af37521..4b47270 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,66 @@ -# UnattendTool -Windows 自动安装应答文件 Unattend.xml 生成工具 +# UnattendTool 简介 + +* 生成 Windows 系统自动安装应答文件 Unattend.xml +* 可搭配 Ventoy 一起使用:https://github.com/ventoy/Ventoy +* 只支持 Windows 10 或 Windows 11 + +# 下载 + +从如下链接下载最新的版本:`UnattendTool_版本号.zip` + +> https://github.com/dsx42/UnattendTool/releases + +# 使用 + +解压,鼠标左键双击运行解压后的 `UnattendTool.cmd` 文件,根据提示操作即可 + +# 支持的选项 + +`UnattendTool.ps1` 支持非交互式运行 + +```powershell +.\UnattendTool.ps1 -Version +``` + +```powershell +.\UnattendTool.ps1 -Interactive +``` + +```powershell +.\UnattendTool.ps1 + [-Language String] + [-OsVersion int] + [-WindowsProductName String] + [-Architecture String] + [-DiskId int] + [-PartitionID int] + [-FullName String] + [-VentoyDriverLetter String] + [-ISOPath String] + [-NotFormat] +``` + +* `-Version`:返回当前工具的版本号 +* `-Interactive`:交互模式运行,作用和鼠标左键双击运行 `UnattendTool.cmd` 文件一样的效果 +* `-Language String`:要安装系统的语言,只支持如下两个值: + * `'zh-CN'`:简体中文;默认值 + * `'en-US'`:英文 +* `-OsVersion int`:要安装系统的版本,只支持如下两个值: + * `11`:Windows 11;默认值 + * `10`:Windows 10 +* `-WindowsProductName String`:要安装系统的产品,支持如下值: + * `'Enterprise'`:企业版;默认值 + * `'Education'`:教育版 + * `'Pro'`:专业版 + * `'Pro Education'`:专业教育版 + * `'Pro For Workstations'`:专业工作站版 + * `''`:空字符串,表示非上述的其他版本 +* `-Architecture String`:要安装系统的架构,只支持如下两个值: + * `'x64'`:64 位系统;默认值 + * `'x86'`:32 位系统;注意,Windows 11 只有 64 位系统 +* `-DiskId int`:要安装系统的硬盘编号,硬盘编号从 0 开始;默认为 -1,表示自动选择当前操作系统所在的硬盘 +* `-PartitionID int`:要安装系统的分区编号,分区编号从 1 开始;默认为 -1,表示自动选择当前操作系统所在的分区 +* `-FullName String`:系统安装后的登录账号名;推荐英文字母或数字的组合,尽量不使用中文或其他特殊字符;默认为 `'MyPC'` +* `-VentoyDriverLetter String`:已安装 Ventoy 的 U 盘驱动器;默认为当前用户的桌面 +* `-ISOPath String`:使用应答文件的 ISO 镜像文件的路径;默认未指定 +* `-NotFormat`:安装系统时不格式化所选硬盘分区;默认安装时会格式化所选硬盘分区 diff --git a/UnattendTool.cmd b/UnattendTool.cmd new file mode 100644 index 0000000..5d5bbb1 --- /dev/null +++ b/UnattendTool.cmd @@ -0,0 +1 @@ +PowerShell -ExecutionPolicy RemoteSigned -File .\UnattendTool.ps1 -Interactive \ No newline at end of file diff --git a/UnattendTool.ps1 b/UnattendTool.ps1 new file mode 100644 index 0000000..884a767 --- /dev/null +++ b/UnattendTool.ps1 @@ -0,0 +1,1272 @@ +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 '按回车键关闭此窗口' diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000..93c8242 --- /dev/null +++ b/build.cmd @@ -0,0 +1 @@ +PowerShell -ExecutionPolicy RemoteSigned -File .\build.ps1 \ No newline at end of file diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..105ca48 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,37 @@ +Set-Location -Path $PSScriptRoot + +$Version = .\UnattendTool.ps1 -Version +$Output = 'target' +$ProjectName = 'UnattendTool' + +$DestinationPath = ".\$Output\${ProjectName}_$Version.zip" + +$Files = @( + '.\UnattendTool.cmd', + '.\UnattendTool.ps1', + '.\LICENSE', + '.\README.md' +) + +if (Test-Path -Path ".\$Output" -PathType Container) { + Remove-Item -Path ".\$Output" -Recurse -Force +} + +New-Item -Path ".\$Output\$ProjectName" -ItemType Directory -Force + +Copy-Item -Path $Files -Destination ".\$Output\$ProjectName" -Force -Recurse + +Compress-Archive -Path ".\$Output\$ProjectName" -DestinationPath $DestinationPath -Force + +$Hash = Get-FileHash -Path $DestinationPath -Algorithm SHA256 + +$Checksum = $Hash.Hash + " ${ProjectName}_$Version.zip" + +Add-Content -Path ".\$Output\${ProjectName}_$Version.sha256" -Value $Checksum + +Write-Host -Object '' +Write-Host -Object ('Path: ' + $Hash.Path) +Write-Host -Object '' +Write-Host -Object ('SHA256: ' + $Hash.Hash) +Write-Host -Object '' +Read-Host -Prompt '按回车键关闭此窗口'