Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| windows:hyper-v:windows-vm-template-deployment-customzation [2026/05/15 09:05] – created chris | windows:hyper-v:windows-vm-template-deployment-customzation [2026/05/19 15:02] (current) – chris | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Virtual Machine Template (Windows) - Deployment and Customization ====== | ====== Virtual Machine Template (Windows) - Deployment and Customization ====== | ||
| + | <code powershell> | ||
| + | Param( | ||
| + | [Parameter(Mandatory=$True)] | ||
| + | [string]$VMName | ||
| + | |||
| + | ) | ||
| + | |||
| + | $AdministratorPassword = " | ||
| + | |||
| + | # Copy VHDX | ||
| + | $NewDiskPath = " | ||
| + | Copy-Item -Path " | ||
| + | |||
| + | # New VM | ||
| + | New-VM -Name $VMName.toUpper() -Generation 2 -MemoryStartupBytes 4GB -Path " | ||
| + | Set-VMProcessor -VMName $VMName -Count 4 | ||
| + | Set-VMFirmware -VMName $VMName -EnableSecureBoot On | ||
| + | |||
| + | # Attach Disk | ||
| + | Add-VMHardDiskDrive -VMName $VMName -Path $NewDiskPath -ControllerType SCSI | ||
| + | Set-VMFirmware -VMName $VMName -FirstBootDevice (Get-VMHardDiskDrive -VMName $VMName) | ||
| + | |||
| + | |||
| + | |||
| + | # Unattend | ||
| + | $Unattend = @" | ||
| + | <?xml version=" | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | publicKeyToken=" | ||
| + | < | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | <!-- German keyboard (QWERTZ) --> | ||
| + | <!-- 0407 = German (Germany) language ID --> | ||
| + | <!-- 00000407 = German keyboard layout --> | ||
| + | < | ||
| + | <!-- Everything else US English --> | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | </ | ||
| + | < | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | "@ | ||
| + | |||
| + | |||
| + | $Disk = Mount-VHD -Path $NewDiskPath -Passthru | ||
| + | $Partition = Get-Partition -DiskNumber $Disk.Number -PartitionNumber 3 | ||
| + | If (-not $Partition.DriveLetter) { | ||
| + | Set-Partition -DiskNumber $Disk.Number -PartitionNumber 3 -NewDriveLetter X | ||
| + | } | ||
| + | $Partition = Get-Partition -DiskNumber $Disk.Number -PartitionNumber 3 | ||
| + | |||
| + | |||
| + | $Unattend | Set-Content -Path X: | ||
| + | $Unattend | Set-Content -Path C: | ||
| + | |||
| + | Dismount-VHD -Path $NewDiskPath | ||
| + | |||
| + | # Start VM | ||
| + | Start-VM -Name $VMName | ||
| + | |||
| + | # Wait VM provisioned | ||
| + | $Seconds = 0 | ||
| + | $Stage = 0 | ||
| + | Do { | ||
| + | $Seconds++ | ||
| + | Start-Sleep -Seconds 1 | ||
| + | $HeartBeat = Get-VMIntegrationService -VMName $VMName -Name " | ||
| + | If ($Stage -in @(0, 2) -and $HeartBeat.PrimaryStatusDescription -eq ' | ||
| + | $Stage++ | ||
| + | } | ||
| + | If ($Stage -eq 1 -and $HeartBeat.PrimaryStatusDescription -ne ' | ||
| + | $Stage++ | ||
| + | } | ||
| + | Write-Host -NoNewLine " | ||
| + | } Until ($Stage -ge 3) | ||
| + | |||
| + | |||
| + | $Credential = New-Object System.Management.Automation.PSCredential (" | ||
| + | |||
| + | |||
| + | Invoke-Command -VMName $VMName -Credential $Credential -ScriptBlock { | ||
| + | Get-NetAdapter | Rename-NetAdapter -NewName " | ||
| + | Get-NetAdapter | New-NetIPAddress -IPAddress 10.58.5.19 -PrefixLength 24 | ||
| + | Get-Netadapter | Set-DnsClientServerAddress -ServerAddresses 10.4.21.181, | ||
| + | } | ||
| + | |||
| + | </ | ||