New-AdminLabVM
Provisions a clean Windows 11 test VM on Hyper-V using an unattend.xml answer file. Configures networking, WinRM, and optional domain join for a repeatable lab baseline.
Overview
New-AdminLabVM provisions a clean Windows 11 test VM on Hyper-V using an unattend.xml answer file. It configures networking, WinRM, and optional domain join for a repeatable lab baseline.
Stop building lab VMs manually. This script gives you a consistent, reproducible starting point for testing Group Policy settings, Intune policies, or hardening scripts before deploying to production.
Tested environment: Windows 11 24H2 Hyper-V host (Hyper-V Version 10.0.26100), Windows 11 24H2 Enterprise ISO. PowerShell 5.1 and 7.4.
Prerequisites
Before running, confirm:
- Hyper-V is enabled on the host:
# Windows 11 host — check Hyper-V feature state
(Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V).State
# Expected: Enabled
# Enable if not already on (requires reboot)
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All- A virtual switch exists on the Hyper-V host. The script attaches the VM to a switch named
Default Switchby default. Verify yours:
Get-VMSwitch | Select-Object Name, SwitchType, NetAdapterInterfaceNameIf your external switch has a different name, supply it via -SwitchName. The Default Switch (type Internal, NAT) works for internet-connected lab VMs. Use an External switch if you need the VM on the same LAN as the host.
-
A Windows 11 ISO — Enterprise or Pro edition, 64-bit. The script mounts the ISO directly; no prior extraction is needed.
-
Sufficient disk space — the script creates a dynamically expanding VHDX (default 127 GB allocated; actual initial size is ~5 GB). Ensure the target
-VhdPathdirectory has enough free space. -
Run as Administrator — Hyper-V cmdlets require local administrator privileges.
Parameters
| Parameter | Type | Description |
|---|---|---|
-VMName | [string] | Name for the new VM. Used for the VM display name and the VHDX filename |
-IsoPath | [string] | Full path to the Windows 11 ISO file |
-VhdPath | [string] | Directory where the VHDX will be created |
-MemoryGB | [int] | Startup RAM in GB. Default: 4 |
-CPUCount | [int] | Virtual CPU count. Default: 2 |
-SwitchName | [string] | Hyper-V virtual switch name. Default: Default Switch |
-VhdSizeGB | [int] | Maximum VHDX size in GB (dynamically expanding). Default: 127 |
-DomainJoin | [switch] | Join the VM to an AD domain after first boot |
-DomainName | [string] | AD domain FQDN to join. Required when -DomainJoin is specified |
-AdminPassword | [securestring] | Local Administrator password for the unattend.xml. Prompted interactively if not supplied |
Usage Examples
Standalone lab VM with interactive password prompt:
New-AdminLabVM -VMName "WIN11-LAB-01" `
-IsoPath "D:\ISOs\Win11_24H2_Enterprise.iso" `
-VhdPath "D:\VMs" `
-MemoryGB 8 -CPUCount 4Specify password non-interactively (for pipeline use):
$pw = ConvertTo-SecureString 'Lab@Password1!' -AsPlainText -Force
New-AdminLabVM -VMName "WIN11-POLICY-TEST" `
-IsoPath "D:\ISOs\Win11_24H2_Enterprise.iso" `
-VhdPath "D:\VMs" `
-AdminPassword $pwDomain-joined lab VM:
New-AdminLabVM -VMName "WIN11-DOMAIN-TEST" `
-IsoPath "D:\ISOs\Win11_24H2_Enterprise.iso" `
-VhdPath "D:\VMs" `
-DomainJoin -DomainName "corp.local"What Gets Configured
The script runs the following steps in sequence:
- Creates a Generation 2 Hyper-V VM with specified CPU and memory. Generation 2 enables Secure Boot (required for Windows 11) and UEFI firmware.
- Attaches the ISO as a DVD drive and sets it as the boot device.
- Creates a dynamically expanding VHDX in
-VhdPathnamed<VMName>.vhdx. - Injects an unattend.xml into the VHDX before first boot. The answer file sets:
- Regional and keyboard locale (
en-US) - Built-in Administrator account enabled with the supplied password
- Auto-logon on first boot to complete setup
- WinRM enabled and set to allow remote management
- Regional and keyboard locale (
- Starts the VM — Windows installs unattended. This typically takes 5–12 minutes depending on host disk speed.
- Waits for WinRM to become available and runs a connectivity test.
- Optionally joins the AD domain using the supplied
-DomainName, then reboots.
Validation
After the script completes, verify the VM is ready:
# Check VM is running and has an IP address
Get-VM -Name "WIN11-LAB-01" | Select-Object Name, State, Uptime
Get-VMNetworkAdapter -VMName "WIN11-LAB-01" | Select-Object IPAddresses
# Test WinRM connectivity
Test-WSMan -ComputerName (Get-VMNetworkAdapter -VMName "WIN11-LAB-01").IPAddresses[0]
# Run a remote command to confirm access
Invoke-Command -ComputerName (Get-VMNetworkAdapter -VMName "WIN11-LAB-01").IPAddresses[0] `
-ScriptBlock { $env:COMPUTERNAME } -Credential (Get-Credential)For domain-joined VMs, also confirm the computer account appears in ADUC and the VM can authenticate against the domain:
Invoke-Command -ComputerName "WIN11-DOMAIN-TEST.corp.local" `
-ScriptBlock { [System.Security.Principal.WindowsIdentity]::GetCurrent().Name }Common Errors
New-VHD : The system cannot find the path specified
The -VhdPath directory does not exist. Create it first: New-Item -ItemType Directory -Path D:\VMs.
Set-VMFirmware : No switches are found or Add-VMNetworkAdapter : Cannot find virtual switch
The virtual switch name specified (or the default Default Switch) does not exist on the host. Run Get-VMSwitch to list available switches and pass the correct name via -SwitchName.
VM boots to UEFI firmware screen instead of Windows setup The ISO is not being detected as a bootable device. Confirm the ISO path is correct and the file is not corrupted:
# Verify ISO file exists and is non-zero
Get-Item "D:\ISOs\Win11_24H2_Enterprise.iso" | Select-Object FullName, LengthAlso confirm the DVD drive is set as the first boot device in the VM firmware: Set-VMFirmware -VMName "WIN11-LAB-01" -FirstBootDevice (Get-VMDvdDrive -VMName "WIN11-LAB-01").
WinRM connection refused after Windows installs
WinRM may not have been configured by the unattend.xml if the ISO edition doesn't support the FirstLogonCommands section used. Connect to the VM console (vmconnect.exe) and manually run:
winrm quickconfig -q
netsh advfirewall firewall add rule name="WinRM-HTTP" dir=in action=allow protocol=TCP localport=5985Add-Computer : The specified domain either does not exist or could not be contacted
For -DomainJoin, the VM must have network access to a domain controller. Confirm the virtual switch the VM is connected to has a route to the AD domain's DNS server and domain controller.
Cleanup and Teardown
To cleanly remove a lab VM when finished:
$VMName = "WIN11-LAB-01"
# Stop and remove the VM (retains the VHDX by default)
Stop-VM -Name $VMName -Force -TurnOff
Remove-VM -Name $VMName -Force
# Remove the VHDX file manually if no longer needed
$VhdxPath = "D:\VMs\$VMName.vhdx"
if (Test-Path $VhdxPath) { Remove-Item $VhdxPath -Force }For domain-joined VMs, also remove the computer account from AD before deleting the VM:
# Remove AD computer account (requires AD PowerShell module)
Remove-ADComputer -Identity $VMName -Confirm:$falseSecurity Notes
- Local administrator password: The unattend.xml sets the built-in Administrator account password. Change this password immediately after first login — treat the provisioned password as a setup credential, not a permanent one. Do not reuse lab VM passwords across environments.
- Do not pass admin passwords as plaintext in scripts that may be logged or stored in source control. Use
ConvertTo-SecureStringwithRead-Host -AsSecureStringfor interactive use, or retrieve from a secrets vault for pipeline use. - WinRM is enabled in HTTP mode (TCP 5985) by the unattend configuration. This is appropriate for isolated lab networks. Do not place lab VMs on production LAN segments with WinRM-HTTP enabled — use HTTPS (TCP 5986) or restrict by firewall rule.
- Secure Boot is enabled by default (Generation 2 VMs). Do not disable Secure Boot on lab VMs unless specifically testing Secure Boot behaviour — keeping it enabled makes the lab environment closer to production and avoids habits of disabling it.
Related Resources
Jack
LinkedInSenior Enterprise Sysadmin · 12+ Years Windows & Intune
I've spent 12+ years managing Windows fleets, Intune tenants, and Active Directory environments for enterprise clients across finance, logistics, and professional services. AdminSignal exists because I got tired of docs that stop at "click Apply." Everything here is tested in production before it goes on the page.
AdminSignal content is produced independently. Editorial policy