New-VHDfromWim.ps1
function New-VHDfromWim { <# .SYNOPSIS Creates a VHD from a WIM-Image .DESCRIPTION This simple Function converts a WIM-Image into a fully functional VHD. It uses the DISM- and Hyper-V Modules. .EXAMPLE New-VHDfromWim -isoImagePath Value -vhdPath Value -diskSize Value -disktype Value -partitionStyle Value Describe what this call does .EXAMPLE New-VHDfromWim -Edition Value Describe what this call does .EXAMPLE New-VHDfromWim -ImageIndex Value Describe what this call does .NOTES Author: Holger Voges Version: 1.0 Date: 18.03.2017 .LINK https://www.netz-weise-it.training/ #> param( # Path to the Windows Iso Image [ValidateScript({ If ( Test-Path -Path $_ -PathType Leaf ) { $true } Else { Throw "$_ is not a valid File." } })] [parameter(mandatory=$true)] [string]$ImagePath, # The Image-Name to install [parameter(mandatory=$true, ParameterSetName='ImageByName')] [string]$Edition, # The Index of the Image to install. You can either type the name or the index of the Image. [parameter(mandatory=$true, ParameterSetName='ImageByIndex')] [Alias('Index')] [int]$ImageIndex, # The Path including the filename of the VHD to create [ValidateScript({ If ( Test-Path -Path $_ -PathType Leaf ) { Throw "File $_ already exists. Please delete the file or chose another Path." } Else { $true } })] [parameter(mandatory=$true)] [string]$vhdPath, # The Size of the VHD [int64]$diskSize = 60GB, # The type of the disk. Fixed uses the full disksize of the vhd at disk-creation. [Validateset('Dynamic','Fixed')] [string]$disktype = 'Dynamic', # The Disk Partitionstyle. Use GPT for Generation 2 VMs. [ValidateSet('GPT','MBR')] [string]$partitionStyle = 'GPT', # Path to a MOF-File for inital DSC configuration [ValidateScript({ If ( Test-Path -Path $_ -PathType Leaf ) { $true } Else { Throw "$_ is not a valid File." } })] [string]$DSCMofPath, # Path to an unattend.xml for inital Sysprep Configuration [ValidateScript({ If ( Test-Path -Path $_ -PathType Leaf ) { $true } Else { Throw "$_ is not a valid File." } })] [string]$UnattendPath, # Enable RDP-Protocol [switch]$EnableRDP, # Add Runonce-Script, will be started for the administrator Account at first Logon [ValidateScript({ If ( Test-Path -Path $_ -PathType Leaf ) { $true } Else { Throw "$_ is not a valid File." } })] [string]$RunOnceUserScript, # Add Runonce-Script, will be started once at first Computer startup [ValidateScript({ If ( Test-Path -Path $_ -PathType Leaf ) { $true } Else { Throw "$_ is not a valid File." } })] [string]$RunOnceComputerScript ) If ( (get-item -path $Imagepath).Extension -eq '.iso' ) { Write-Verbose "Iso-Image: $ImagePath" $iso = Mount-DiskImage -ImagePath $ImagePath -StorageType ISO -PassThru $DSCConfigPath = 'Windows\System32\Configuration' $SysprepPath = 'Windows\System32\sysprep' # Workaround, as ISO-Drive might be not available elsewise $null = Get-PSDrive $IsoDriveletter = (Get-Volume -DiskImage $iso).DriveLetter + ':' $wimPath = join-path $IsoDriveletter 'sources\install.wim' } Elseif ( (get-item -path $Imagepath).Extension -eq '.wim' ) { $wimPath = $ImagePath } Else { Throw 'Das Image muß ein Iso-File oder ein gültiges Wim-File sein' } $imageToInstall = get-windowsimage -ImagePath $wimPath | Where-Object { $_.ImageName -eq "$Edition" -or $_.ImageIndex -eq $ImageIndex } If (-not $imageToInstall) { 'Wrong Image Name. Please choose of the following:' get-windowsimage -ImagePath $wimPath If ( $iso ) { Dismount-DiskImage -ImagePath $iso.ImagePath } break } $imageIndex = $imageToInstall.ImageIndex $vhd = New-VHD -Path $vhdPath -SizeBytes $diskSize -Dynamic -ErrorAction Stop $vhd = $vhd | Mount-VHD -Passthru Switch ( $partitionStyle ) { 'GPT' { $Partitions = New-GPTDisk -vhd $vhd -disktype $disktype } 'MBR' { $Partitions = New-MBRDisk -vhd $vhd -disktype $disktype } } $logPath = Expand-WindowsImage -ImagePath $wimPath -Index $imageIndex[0] -ApplyPath ($Partitions.Data.DriveLetter + ':\') $bcdexe = join-Path -Path ( $Partitions.Data.DriveLetter + ':\' ) -ChildPath 'Windows\System32\bcdboot.exe' Write-Verbose "BCD-Command: $bcdexe" $ResultMessage = & $bcdexe "$($Partitions.Data.DriveLetter):\Windows" /s ($Partitions.Boot.DriveLetter + ':' ) /f ALL # Registry aus VHD mounten # $VhdRegistry = "$($Partitions.Data.DriveLetter):\windows\system32\config\System" $RegPath = Mount-VHDRegistry -DriveLetter $Partitions.Data.DriveLetter -Tree System Switch ( $PSBoundParameters ) { { $PSBoundParameters.EnableRDP } { Enable-RDP -RegPath $regPath } # ToDo: Call Function { $PSBoundParameters.RunOnceUserScript } { 'Implement Code here' } # ToDo: Call Function { $PSBoundParameters.RunOnceComputerScript } { 'Implement Code here' } # ToDo: Call Function { $PSBoundParameters.UnattendPath } { Add-File -FilePath $UnattendPath -OsDrive $Partitions.Data.DriveLetter -TargetPath $sysPrepPath } { $PSBoundParameters.DSCMofPath } { Add-File -FilePath $DSCMofPath -OsDrive $Partitions.Data.DriveLetter -TargetPath $DSCConfigPath -NewFileName pending.mof } # { $PSBoundParameters.DSCMofPath } { Add-MOF -DSCMofPath C:\temp\localhost.mof -OsDrive $Partitions.Data.DriveLetter } } Dismount-VHDRegistry # Systempartition konfigurieren Write-Verbose -Message $Partitions.Boot.Driveletter Switch ( $partitionStyle ) { 'GPT' { Set-Partition -DriveLetter $Partitions.Boot.Driveletter -GptType $PartitionType.EFI } # 'MBR' { Set-Partition -DriveLetter $Partitions.Boot.Driveletter -IsActive $true } } Write-Verbose "Dismounting Disk $($Vhd.Disknumber)" Dismount-VHD -DiskNumber $vhd.DiskNumber Write-Verbose "Dismount Iso $($iso.ImagePath)" Dismount-DiskImage -ImagePath $iso.ImagePath } |