In my lab environment, I am constantly deploying different Virtual Machines. I’ve built up a number of template vhdx files which are either sysprep’d installs of Windows Server or custom images ready to go. Manually setting up VMs via the User interface can be a little time consuming, so I’ve written up a small PowerShell script that helps with building and configuring a Virtual Machine.

The script is quite basic and, uses BITS to copy so you get a progress bar and most things are hard-coded. It’s worked for a number of years without fail, but could probably do with some modernisation. I’m posting it since it works for me, and it’s what I use for the lab. Feel free to re-use and cannibalise as you want (or trash).
Import-Module BitsTransfer
#Defining Variables. Change these patch to your own!
$2019STD = "C:\Templates\Server 2019 Standard Template.vhdx"
$2022STD = "C:\Templates\Server 2022 Standard Template.vhdx"
$2025STD = "C:\Templates\Server 2025 Standard Template.vhdx"
$WIN11 = "C:\Templates\Windows 11 Enterprise Template.vhdx"
#Cleaning screen
cls
# Offer choice in which OS to deploy
Do {
Write-host
Write-host "Which operating system would you like to deploy?" -foregroundcolor Green
Write-host
Write-host "1. Server 2019 Standard" -foregroundcolor Red
Write-host "2. Server 2022 Standard" -foregroundcolor Red
Write-host "3. Server 2025 Standard" -foregroundcolor Green
Write-host "4. Windows 11 Enterprise" -foregroundcolor Blue
$deploy = Read-host "Please select an operating system image to continue..."
if ($deploy -eq "") {write-host "Error: Please select and operating system image" -foregroundcolor Red}; if ($deploy -eq $NULL) {write-host "Error: Please select an operating system image" -foregroundcolor Red}
write-host
} while ($deploy -eq "" -or $deploy -eq $NULL)
# What should the VM be called
Do {
$Name = Read-Host "Enter the Virtual Machine name (Press [Enter] to choose Server01)"
if ($Name -eq ""){$Name="Server01"} ; if ($Name -eq $NULL){$Name="Server01"}
$VMName = Get-VM -name $Name -ErrorAction SilentlyContinue
if (!$VMname) { Write-Host "No VM named $Name exists" }
else
{ Write-Host "Error: A VM with the name $Name already exists" -foregroundcolor Red; $Name = $null }
} while ($Name -eq $null)
#how much memory needs to be assigned (static only at this point)
$Memory = Read-Host "Enter the size of the Virtual Machine Memory (Press [Enter] to choose 4096MB)"
if ($Memory -eq ""){$Memory=4096MB} ; if ($Memory -eq $NULL){$Memory=4096MB}
# How many CPU cores do you want assigned
$Cores = Read-Host "Enter how many Virtual Processors to assign the Virtual Machine (Press [Enter] to have 2 Cores)"
if ($Cores -eq ""){$Cores=2} ; if ($Cores -eq $NULL){$Cores=2}
#Where should the VM be stored
$Location = Read-Host "Enter the location of the Virtual Machine file (Press [Enter] to choose E:\Hyper-V)"
if ($Location -eq ""){$Location="E:\Hyper-V"} ; if ($Location -eq $NULL){$Location="E:\Hyper-V"}
#Listing networks on the host
Write-host
get-vmswitch
write-host
#Which network should be used
$Network = Read-Host "Enter the name of the Virtual Machine Network (Press [Enter] to choose External)"
if ($Network -eq ""){$Network="External"} ; if ($Network -eq $NULL){$Network="External"}
#VM creation starts here
Switch ($deploy)
{
1 {new-vm $Name -Generation 2 -path $Location ;New-Item $Location\$Name\"Virtual Hard Disks" -type directory; Start-BitsTransfer -Source $2019STD -Destination $Location\$Name\"Virtual Hard Disks\"$Name".vhdx" -Description "Windows Server 2019.vhdx" -DisplayName "Copying template VHDX" ; add-vmharddiskdrive -vmname $Name -path $Location\$Name\"Virtual Hard Disks\"$Name".vhdx" }
2 {new-vm $Name -Generation 2 -path $Location ;New-Item $Location\$Name\"Virtual Hard Disks" -type directory; Start-BitsTransfer -Source $2022STD -Destination $Location\$Name\"Virtual Hard Disks\"$Name".vhdx" -Description "Windows Server 2022.vhdx" -DisplayName "Copying template VHDX" ; add-vmharddiskdrive -vmname $Name -path $Location\$Name\"Virtual Hard Disks\"$Name".vhdx" }
3 {new-vm $Name -Generation 2 -path $Location ;New-Item $Location\$Name\"Virtual Hard Disks" -type directory; Start-BitsTransfer -Source $2025STD -Destination $Location\$Name\"Virtual Hard Disks\"$Name".vhdx" -Description "Windows Server 2025.vhdx" -DisplayName "Copying template VHDX" ; add-vmharddiskdrive -vmname $Name -path $Location\$Name\"Virtual Hard Disks\"$Name".vhdx" }
4 {new-vm $Name -Generation 2 -path $Location ;New-Item $Location\$Name\"Virtual Hard Disks" -type directory; Start-BitsTransfer -Source $WIN11 -Destination $Location\$Name\"Virtual Hard Disks\"$Name".vhdx" -Description "Windows 11 Enterprise.vhdx" -DisplayName "Copying template VHDX" ; add-vmharddiskdrive -vmname $Name -path $Location\$Name\"Virtual Hard Disks\"$Name".vhdx" }
}
get-vm $Name | Add-VMDvdDrive -ControllerNumber 0
get-vm $Name | Set-VMProcessor -Count $Cores
get-vm $Name | Set-VMMemory -StartupBytes $Memory -DynamicMemoryEnabled 1
Get-VMSwitch $Network | Connect-VMNetworkAdapter -VMName $Name
#Success message.
Switch ($deploy)
{
1 {Write-host "A Windows 2019 Standard VM called '$Name' Deployed Successfully!" -foregroundcolor Green}
2 {Write-host "Windows 2022 Standard VM called '$Name' Deployed Successfully!" -foregroundcolor Green}
3 {Write-host "Windows 2025 Standard VM called '$Name' Deployed Successfully!" -foregroundcolor Green}
4 {Write-Host "Windows 11 Enterprise VM called '$Name' Deployed Successfully!" -foregroundcolor Green}
}
By default, it’ll give 4GB of Memory, 2 CPU Cores and assign an Ethernet Adapter called “External” and create VMs under the E drive in a Hyper-V folder, creating a sub-folder for each VM you create.
All this can be customised within the code to do what you want.
Hope that helps.

Leave a Reply