modules/Initialize-WindowsVM.psm1
Set-StrictMode -Version Latest . "$PSSCriptRoot\..\detail\Assert-RunningAsAdmin.ps1" . "$PSSCriptRoot\..\detail\Invoke-WithResource.ps1" function Initialize-WindowsVM { [OutputType([HyperV.Tools.VM])] [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ParameterSetName = "WIM x VM x ImageName")] [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ParameterSetName = "WIM x VM x ImageIndex")] [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ParameterSetName = "ISO x VM x ImageName")] [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ParameterSetName = "ISO x VM x ImageIndex")] [HyperV.Tools.VM] [Alias("VM")] $InputObject, [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ParameterSetName = "WIM x VMName x ImageName")] [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ParameterSetName = "WIM x VMName x ImageIndex")] [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ParameterSetName = "ISO x VMName x ImageName")] [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ParameterSetName = "ISO x VMName x ImageIndex")] [string] $VMName, [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "WIM x VM x ImageName")] [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "WIM x VM x ImageIndex")] [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "WIM x VMName x ImageName")] [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "WIM x VMName x ImageIndex")] [string] $WIMPath, [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "ISO x VM x ImageName")] [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "ISO x VM x ImageIndex")] [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "ISO x VMName x ImageName")] [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "ISO x VMName x ImageIndex")] [string] $ISOPath, [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "WIM x VM x ImageName")] [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "ISO x VM x ImageName")] [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "WIM x VMName x ImageName")] [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "ISO x VMName x ImageName")] [string] $ImageName, [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "WIM x VM x ImageIndex")] [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "ISO x VM x ImageIndex")] [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "WIM x VMName x ImageIndex")] [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "ISO x VMName x ImageIndex")] [int] $ImageIndex, [Parameter(Mandatory = $false, Position = 3)] [AllowEmptyString()] [string] $UnattendXMLContents ) Assert-RunningAsAdmin $parameters_to_pass_through = [hashtable]$PSBoundParameters #region Handle VM / VMName parameters if ($PSCmdlet.ParameterSetName -like "* x VM x *") { $VM = $InputObject } elseif ($PSCmdlet.ParameterSetName -like "* x VMName x *") { $VM = Hyper-V\Get-VM -Name $VMName } else { throw "Unknown parameter set name: $($PSCmdlet.ParameterSetName)" } $parameters_to_pass_through.Remove("InputObject") $parameters_to_pass_through.Remove("VMName") #endregion #region Handle ISOPath parameter and prepare ScriptBlocks for `Invoke-WithResource` if ($PSCmdlet.ParameterSetName -like "ISO x *") { $mount_ISO_block = { [Diagnostics.CodeAnalysis.SuppressMessage('PSUseDeclaredVarsMoreThanAssignments', '')] $mounted_ISO = Mount-DiskImage -ImagePath $ISOPath $mounted_ISO_drive_letter = ($mounted_iso | Get-Volume | Select-Object -ExpandProperty "DriveLetter") + ":\" [Diagnostics.CodeAnalysis.SuppressMessage('PSUseDeclaredVarsMoreThanAssignments', '')] $WIMPath = Join-Path -Path $mounted_ISO_drive_letter -ChildPath "sources\install.wim" } $dismount_ISO_block = { $mounted_ISO | Dismount-DiskImage | Out-Null Remove-Variable -Name "mounted_ISO" } } $parameters_to_pass_through.Remove("ISOPath") $parameters_to_pass_through.Remove("WIMPath") #endregion Invoke-WithResource -InitBlock $mount_ISO_block -CleanupBlock $dismount_ISO_block -BodyBlock { initialize_Windows_VM -VM $VM -WIMPath $WIMPath @parameters_to_pass_through } return $VM } function initialize_Windows_VM { [CmdletBinding(PositionalBinding = $false)] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [HyperV.Tools.VM] [Alias("VM")] $InputObject, [Parameter(Mandatory = $true)] [string] $WIMPath, [Parameter(Mandatory = $true, ParameterSetName = "ImageName")] [string] $ImageName, [Parameter(Mandatory = $true, ParameterSetName = "ImageIndex")] [int] $ImageIndex, [Parameter(Mandatory = $false)] [AllowEmptyString()] [string] $UnattendXMLContents ) $VM = $InputObject $HDD_count = $VM.HardDrives.Count if ($HDD_count -ne 1) { throw "Virtual Machine must have exactly 1 hard drive but has $HDD_count drives." } $VHD_path = $VM.HardDrives[0].Path $image_info = Get-WindowsImage -ImagePath $WIMPath if ($PSCmdlet.ParameterSetName -eq "ImageName") { $image_index = $image_info | Where-Object -Property "ImageName" -eq $ImageName | Select-Object -ExpandProperty "ImageIndex" if ($null -eq $image_index) { throw "Image '$ImageName' not found in WIM file." } } elseif ($PSCmdlet.ParameterSetName -eq "ImageIndex") { $image_index = $image_info | Where-Object -Property "ImageIndex" -eq $ImageIndex | Select-Object -ExpandProperty "ImageIndex" if ($null -eq $image_index) { throw "Image #'$ImageIndex' not found in WIM file." } } else { throw "Unknown parameter set name: $($PSCmdlet.ParameterSetName)" } Initialize-VHDFromWIM -Path $VHD_path -WIMPath $WIMPath -ImageIndex $image_index -UnattendXMLContents $UnattendXMLContents } |