modules/Initialize-DiskFromWIM.psm1
Set-StrictMode -Version "Latest" . "$PSSCriptRoot\..\detail\Assert-RunningAsAdmin.ps1" . "$PSScriptRoot\..\detail\Invoke-WithResource.ps1" function Initialize-DiskFromWIM { [OutputType([CimInstance])] [OutputType("Microsoft.Management.Infrastructure.CimInstance#ROOT/Microsoft/Windows/Storage/MSFT_Disk")] [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [CimInstance] [ValidateCimInstance("MSFT_Disk", "root\Microsoft\Windows\Storage")] [Alias("Disk")] $InputObject, [Parameter(Mandatory = $true)] [string] $WIMPath, [Parameter(Mandatory = $true)] [int] $ImageIndex, [Parameter(Mandatory = $false)] [ValidateSet("GPT", "MBR")] [string] $PartitionStyle = "GPT", [Parameter(Mandatory = $false)] [AllowEmptyString()] [string] $UnattendXMLContents, [Parameter(Mandatory = $false)] [Switch] $CreateRecoveryPartition ) Assert-RunningAsAdmin # Any error should make us stop. $ErrorActionPreference = "Stop" $target_disk = $InputObject Set-Variable -Option "Constant" -Name "GPT_PARTITION_TYPE_ESP" -Value "{c12a7328-f81f-11d2-ba4b-00a0c93ec93b}" Set-Variable -Option "Constant" -Name "GPT_PARTITION_TYPE_MSR" -Value "{e3c9e316-0b5c-4db8-817d-f92df00215ae}" Set-Variable -Option "Constant" -Name "GPT_PARTITION_TYPE_RECOVERY" -Value "{de94bba4-06d1-4d40-a16a-bfd50179d6ac}" Set-Variable -Option "Constant" -Name "MSR_PARTITION_SIZE" -Value 16MB Set-Variable -Option "Constant" -Name "BOOT_PARTITION_SIZE" -Value 350MB Set-Variable -Option "Constant" -Name "RECOVERY_PARTITION_SIZE" -Value 800MB #region Create partitions $target_disk | Initialize-Disk -PartitionStyle $PartitionStyle if ($PartitionStyle -eq "GPT") { $ESP = $target_disk | New-Partition -AssignDriveLetter -Size $BOOT_PARTITION_SIZE -GptType $GPT_PARTITION_TYPE_ESP $ESP | Format-Volume -FileSystem "FAT32" -NewFileSystemLabel "System" | Out-Null $target_disk | New-Partition -AssignDriveLetter -Size $MSR_PARTITION_SIZE -GptType $GPT_PARTITION_TYPE_MSR | Out-Null $system_drive_letter = $ESP.DriveLetter + ":\" Write-Verbose "ESP drive letter: $system_drive_letter" if ($CreateRecoveryPartition -eq $true) { $recovery_partition = $target_disk | New-Partition -AssignDriveLetter -Size $RECOVERY_PARTITION_SIZE } } else { $system_partition = $target_disk | New-Partition -AssignDriveLetter -Size $BOOT_PARTITION_SIZE -MbrType "IFS" -IsActive $system_partition | Format-Volume -FileSystem "NTFS" -NewFileSystemLabel "System" | Out-Null $system_drive_letter = $system_partition.DriveLetter + ":\" Write-Verbose "MBR System drive letter: $system_drive_letter" if ($CreateRecoveryPartition -eq $true) { $recovery_partition = $target_disk | New-Partition -AssignDriveLetter -Size $RECOVERY_PARTITION_SIZE -MbrType "IFS" } } $recovery_partition | Format-Volume -FileSystem "NTFS" -NewFileSystemLabel "Recovery" | Out-Null $recovery_partition | Set-Partition -NoDefaultDriveLetter $true -IsHidden $true $recovery_drive_letter = $recovery_partition.DriveLetter + ":\" # We didn't pick the correct parition type using the -GptType parameter when calling New-Partition because # then the call to Set-Partition above (-NoDefaultDriveLetter $true -IsHidden $true) would fail. # So we create the partition, then set it to hidden etc. and then set the partition type to recovery. if ($PartitionStyle -eq "GPT") { $recovery_partition | Set-Partition -GptType $GPT_PARTITION_TYPE_RECOVERY } $windows_partition = $target_disk | New-Partition -AssignDriveLetter -UseMaximumSize $windows_partition | Format-Volume -FileSystem "NTFS" -NewFileSystemLabel "Windows" | Out-Null $windows_drive_letter = $windows_partition.DriveLetter + ":\" Write-Verbose "Windows drive letter: $windows_drive_letter" #endregion Expand-WindowsImage -ImagePath $WIMPath -Index $ImageIndex -ApplyPath $windows_drive_letter | Out-Null #region BCDBoot $target_Windows_path = Join-Path -Path $windows_drive_letter -ChildPath "Windows" $BCDBoot_path = Join-Path -Path $Env:SystemRoot -ChildPath "System32\bcdboot.exe" $BCDBoot_args = "$target_Windows_path /S $system_drive_letter" if ($PartitionStyle -eq "MBR") { $BCDBoot_args += " /F BIOS" } else { $BCDBoot_args += " /F UEFI" } Start-Process -Wait -WindowStyle "Hidden" -FilePath $BCDBoot_path -ArgumentList $BCDBoot_args #endregion if ($UnattendXMLContents -ne "") { $Panther_path = Join-Path -Path $target_Windows_path -ChildPath "Panther\" New-Item -ItemType "Directory" -Path $Panther_path | Out-Null $unattendXML_path = Join-Path -Path $Panther_path -ChildPath "unattend.xml" Set-Content -Path $unattendXML_path -Value $UnattendXMLContents } #region ReAgentc if ($CreateRecoveryPartition -eq $true) { $source_WinRE_WIM = Join-Path -Path $target_Windows_path -ChildPath "System32\Recovery\WinRE.wim" $dest_WinRE_directory = Join-Path -Path $recovery_drive_letter -ChildPath "Recovery\WindowsRE" $ReAgentc_path = Join-Path -Path $Env:SystemRoot -ChildPath "System32\ReAgentc.exe" $ReAgentc_args = "/setreimage /path $dest_WinRE_directory /target $target_Windows_path" New-Item -ItemType "Directory" -Path $dest_WinRE_directory | Out-Null Copy-Item -Path $source_WinRE_WIM -Destination $dest_WinRE_directory Start-Process -Wait -WindowStyle "Hidden" -FilePath $ReAgentc_path -ArgumentList $ReAgentc_args } #endregion Write-Output $target_disk } |