PowerShell Hyper-V: Manage Virtual Machines with PowerShell

PowerShell Hyper-V: Manage Virtual Machines with PowerShell

PowerShell Tips Editor 3 min read
PowerShell Hyper-V: Manage Virtual Machines with PowerShell

Provisioning a test virtual machine by clicking through Hyper-V Manager takes five minutes of clicking, every single time. With the PowerShell Hyper-V module, the same operation is a 10-second script that runs identically every time, can be version-controlled, and integrates into automated build pipelines. This post covers listing VMs, starting and stopping them, creating new VMs, managing checkpoints, querying resource usage, and exporting and importing virtual machine configurations.

List All VMs and Status

The Hyper-V module is automatically available on Windows hosts with the Hyper-V role installed. Get-VM returns all virtual machines and their current state:

Get-VM | Select-Object Name, State, CPUUsage,
    @{N='MemoryGB'; E={ [Math]::Round($_.MemoryAssigned / 1GB, 1) }},
    Uptime, Version |
    Format-Table -AutoSize
Name          State   CPUUsage MemoryGB Uptime           Version
----          -----   -------- -------- ------           -------
WebServer01   Running 2        4.0      2.05:12:34.0     9.0
TestDC        Running 0        2.0      5.01:44:10.0     9.0
DevSandbox    Off     0        0.0      00:00:00.0       9.0

Start, Stop, and Restart VMs

Control VM power state with Start-VM, Stop-VM, and Restart-VM. Use -Force with Stop-VM for an immediate power-off when the OS is unresponsive:

# Start a VM
Start-VM -Name "DevSandbox"

# Graceful shutdown (sends shutdown command to OS)
Stop-VM -Name "DevSandbox"

# Force power off — equivalent to pulling the plug
Stop-VM -Name "DevSandbox" -Force -TurnOff

# Restart
Restart-VM -Name "WebServer01" -Force

# Bulk start all VMs that are off
Get-VM | Where-Object State -eq Off | Start-VM

# Wait for a VM to reach Running state
while ((Get-VM -Name "DevSandbox").State -ne 'Running') {
    Start-Sleep -Seconds 3
}
Write-Host "DevSandbox is now running"

Create a New VM

Create a VM with a specific memory size, number of vCPUs, and virtual hard disk. A generation 2 VM supports UEFI and Secure Boot:

$vmName    = "TestServer2026"
$vmPath    = "D:\VMs"
$vhdPath   = "D:\VMs\$vmName\${vmName}.vhdx"
$isoPath   = "D:\ISOs\WindowsServer2022.iso"

# Create the VM
New-VM -Name $vmName -MemoryStartupBytes 4GB -Generation 2 `
    -NewVHDPath $vhdPath -NewVHDSizeBytes 80GB -Path $vmPath

# Configure vCPUs
Set-VM -Name $vmName -ProcessorCount 4

# Enable Dynamic Memory
Set-VMMemory -VMName $vmName -DynamicMemoryEnabled $true `
    -MinimumBytes 2GB -MaximumBytes 8GB

# Attach ISO for OS installation
Add-VMDvdDrive -VMName $vmName
Set-VMDvdDrive -VMName $vmName -Path $isoPath

Write-Host "VM '$vmName' created. Start it to begin OS installation."

Create and Restore Checkpoints

Checkpoints (snapshots) save a VM’s state at a point in time. Create one before risky changes and restore if something goes wrong:

$vmName   = "TestServer2026"
$snapName = "Pre-PatchTuesday_$(Get-Date -Format 'yyyyMMdd')"

# Create a checkpoint
Checkpoint-VM -Name $vmName -SnapshotName $snapName
Write-Host "Checkpoint '$snapName' created"

# List checkpoints
Get-VMCheckpoint -VMName $vmName | Select-Object Name, CreationTime, ParentSnapshotName

# Restore a checkpoint
$checkpoint = Get-VMCheckpoint -VMName $vmName -Name $snapName
Restore-VMCheckpoint -VMCheckpoint $checkpoint -Confirm:$false
Write-Host "Restored to checkpoint '$snapName'"

# Remove old checkpoints
Get-VMCheckpoint -VMName $vmName |
    Where-Object CreationTime -lt (Get-Date).AddDays(-30) |
    Remove-VMCheckpoint

Get VM Resource Usage

Query CPU, memory, and disk metrics for running VMs using Measure-VM and Get-VM:

Get-VM | Where-Object State -eq Running | ForEach-Object {
    $metrics = Measure-VM -VM $_
    [PSCustomObject]@{
        Name         = $_.Name
        CPUUsagePct  = $_.CPUUsage
        MemoryGB     = [Math]::Round($_.MemoryAssigned / 1GB, 2)
        AvgDiskIOPS  = [Math]::Round($metrics.AverageNormalizedIOPS, 0)
    }
} | Sort-Object CPUUsagePct -Descending | Format-Table -AutoSize

Export and Import VMs

Export a VM to a folder for backup or migration, then import it on the same or a different Hyper-V host:

$vmName    = "DevSandbox"
$exportDir = "D:\VMExports"

# Stop the VM before export (optional but recommended for consistency)
Stop-VM -Name $vmName -Force

# Export the VM
Export-VM -Name $vmName -Path $exportDir
Write-Host "Exported to $exportDir\$vmName"

# Import on same or different host
$vmFolder = "$exportDir\$vmName\Virtual Machines"
$vmConfig = (Get-ChildItem $vmFolder -Filter "*.vmcx").FullName
Import-VM -Path $vmConfig -Copy -GenerateNewId -VhdDestinationPath "D:\VMs"
Write-Host "Import complete"

Common Errors and Fixes

  • Hyper-V module only available when Hyper-V role is installed. The module is not present on systems without the Hyper-V role. On Windows Server, install with Install-WindowsFeature Hyper-V -IncludeManagementTools. On Windows 10/11 Pro or Enterprise, enable via Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-All.
  • VM name must be unique on the host. New-VM fails if a VM with the same name already exists on the host. Check with Get-VM -Name $vmName -ErrorAction SilentlyContinue before creating. Use -GenerateNewId during import to avoid GUID conflicts.

Related Cmdlets / See Also

Wrapping Up

The Hyper-V module gives you full VM lifecycle management from creation to export. Script your standard VM builds for consistent test environments, create pre-change checkpoints before every patch cycle, and use bulk operations on Get-VM output to control entire VM fleets simultaneously.

Send-Item -To