How to Use PowerShell to Manage Hyper-V VMs on Windows Server 2022

PowerShell is the primary management interface for Hyper-V on Windows Server 2022. While Hyper-V Manager provides a GUI, PowerShell gives you automation, bulk operations, remote management, and capabilities that simply do not exist in the GUI. This guide covers the full Hyper-V PowerShell module and practical techniques for managing virtual machines efficiently in production environments.

Exploring the Hyper-V PowerShell Module

Before managing VMs, it helps to understand what commands are available. The Hyper-V module ships with Windows Server 2022 when the Hyper-V role is installed. List all available commands with:

Get-Command -Module Hyper-V

This returns over 200 cmdlets covering everything from VM creation to replication. To see commands grouped by noun, which reveals related functionality:

Get-Command -Module Hyper-V | Group-Object -Property Noun | Sort-Object Count -Descending

To import the module explicitly (it auto-loads on Server 2022 but useful in scripts):

Import-Module Hyper-V

Check the module version installed on your host:

Get-Module -Name Hyper-V -ListAvailable | Select-Object Name, Version, ModuleBase

Listing and Querying Virtual Machines

The Get-VM cmdlet is your starting point for any VM management task. By default it returns all VMs on the local host:

Get-VM

Filter by state to find only running VMs:

Get-VM | Where-Object { $_.State -eq 'Running' }

Get a specific VM by name:

Get-VM -Name "WebServer01"

View detailed properties of a VM including CPU, memory, and uptime:

Get-VM -Name "WebServer01" | Select-Object *

Get CPU usage statistics for all running VMs:

Get-VM | Where-Object { $_.State -eq 'Running' } | Select-Object Name, CPUUsage, MemoryAssigned, Uptime

Managing VM State: Start, Stop, Suspend, and Save

Controlling VM power state is straightforward with dedicated cmdlets. Start a VM:

Start-VM -Name "WebServer01"

Stop a VM gracefully (sends shutdown signal to the guest OS via Integration Services):

Stop-VM -Name "WebServer01"

Force a hard power off (equivalent to pulling the power cord — use only when the guest is unresponsive):

Stop-VM -Name "WebServer01" -Force -TurnOff

Suspend a VM (pauses execution, keeps state in memory):

Suspend-VM -Name "WebServer01"

Resume a suspended VM:

Resume-VM -Name "WebServer01"

Save a VM (hibernate-like state — writes memory to disk and stops):

Save-VM -Name "WebServer01"

Restart a VM gracefully:

Restart-VM -Name "WebServer01" -Force

Creating New Virtual Machines

Create a new Generation 2 VM with a specific amount of startup memory and connected to a virtual switch:

New-VM -Name "AppServer02" `
    -Generation 2 `
    -MemoryStartupBytes 4GB `
    -SwitchName "External Switch" `
    -NewVHDPath "D:VMsAppServer02AppServer02.vhdx" `
    -NewVHDSizeBytes 80GB `
    -Path "D:VMsAppServer02"

After creating the VM, attach an ISO for installation:

Add-VMDvdDrive -VMName "AppServer02" -Path "E:ISOsWS2022.iso"

Set the boot order so the VM boots from DVD first:

$dvd = Get-VMDvdDrive -VMName "AppServer02"
Set-VMFirmware -VMName "AppServer02" -FirstBootDevice $dvd

Configuring VM Settings with Set-VM

The Set-VM cmdlet modifies core VM properties. Rename a VM:

Set-VM -Name "AppServer02" -NewName "WebFrontend01"

Set a VM notes description:

Set-VM -Name "WebFrontend01" -Notes "Production web frontend - deployed 2026-05-17"

Enable automatic start on host boot with a 30-second delay:

Set-VM -Name "WebFrontend01" -AutomaticStartAction Start -AutomaticStartDelay 30

Configure what happens when the Hyper-V host shuts down:

Set-VM -Name "WebFrontend01" -AutomaticStopAction ShutDown

Valid values for AutomaticStopAction are TurnOff, Save, and ShutDown. For production VMs, ShutDown is the safest option as it sends a proper shutdown signal.

Configuring Virtual Processors

Adjust the number of virtual processors assigned to a VM (VM must be off or this can be done on WS2022 hot-add enabled VMs):

Set-VMProcessor -VMName "WebFrontend01" -Count 4

Configure NUMA topology for a VM that needs predictable memory access patterns:

Set-VMProcessor -VMName "WebFrontend01" -Count 8 -MaximumCountPerNumaNode 4 -MaximumCountPerNumaSocket 8

Limit CPU usage to prevent a noisy neighbor from consuming all host CPU resources:

Set-VMProcessor -VMName "WebFrontend01" -Maximum 50 -Reserve 10 -RelativeWeight 100

The -Maximum parameter caps CPU usage at a percentage of total host CPU capacity. -Reserve guarantees a minimum percentage. -RelativeWeight (1-10000) determines priority when CPU is contended.

Enable hardware performance counters pass-through (useful for profiling workloads in VMs):

Set-VMProcessor -VMName "WebFrontend01" -HwThreadCountPerCore 2

Managing VM Memory and Dynamic Memory

Set static memory for a VM:

Set-VMMemory -VMName "WebFrontend01" -StartupBytes 8GB

Enable Dynamic Memory, which allows Hyper-V to adjust the amount of RAM allocated to a VM based on demand:

Set-VMMemory -VMName "WebFrontend01" `
    -DynamicMemoryEnabled $true `
    -MinimumBytes 2GB `
    -StartupBytes 4GB `
    -MaximumBytes 16GB `
    -Buffer 20 `
    -Priority 80

The -Buffer parameter (percentage, 5-2000) tells Hyper-V how much extra memory to try to keep available above what the VM is currently using. The -Priority (1-100) controls how aggressively memory is allocated to this VM compared to others when the host is under memory pressure.

Check current memory status of all VMs:

Get-VMMemory -VMName * | Select-Object VMName, DynamicMemoryEnabled, Minimum, Startup, Maximum, Buffer, Priority

Network Adapter Management

List network adapters for a VM:

Get-VMNetworkAdapter -VMName "WebFrontend01"

Add a new network adapter and connect it to a virtual switch:

Add-VMNetworkAdapter -VMName "WebFrontend01" -SwitchName "Internal Switch" -Name "Management"

Connect an existing disconnected adapter to a switch:

Connect-VMNetworkAdapter -VMName "WebFrontend01" -Name "Management" -SwitchName "Internal Switch"

Configure a VLAN ID on a VM’s network adapter:

Set-VMNetworkAdapterVlan -VMName "WebFrontend01" -VMNetworkAdapterName "Management" -Access -VlanId 100

Enable bandwidth management to limit network throughput:

Set-VMNetworkAdapter -VMName "WebFrontend01" -Name "Management" `
    -MaximumBandwidth 1000000000 `
    -MinimumBandwidthWeight 10

The bandwidth values are in bits per second. 1000000000 = 1 Gbps. Remove a network adapter:

Remove-VMNetworkAdapter -VMName "WebFrontend01" -Name "Management"

Disk Operations: New-VHD, Resize-VHD, and Mount-VHD

Create a new dynamically expanding VHDX disk:

New-VHD -Path "D:VMsWebFrontend01DataDisk.vhdx" -SizeBytes 200GB -Dynamic

Create a fixed-size VHDX for predictable I/O performance:

New-VHD -Path "D:VMsWebFrontend01DataDisk-Fixed.vhdx" -SizeBytes 200GB -Fixed

Attach a VHDX to a running VM (SCSI controller required, not IDE):

Add-VMHardDiskDrive -VMName "WebFrontend01" -Path "D:VMsWebFrontend01DataDisk.vhdx" -ControllerType SCSI

Resize an existing VHDX online (VM can be running for expand operations):

Resize-VHD -Path "D:VMsWebFrontend01DataDisk.vhdx" -SizeBytes 500GB

After resizing at the Hyper-V level, you still need to extend the partition inside the VM using Resize-Partition or Disk Management. Mount a VHDX on the host for direct file access (useful for recovery):

Mount-VHD -Path "D:VMsWebFrontend01DataDisk.vhdx" -ReadOnly

Dismount when done:

Dismount-VHD -Path "D:VMsWebFrontend01DataDisk.vhdx"

Convert a VHD to VHDX format (VM must be off):

Convert-VHD -Path "D:VMsOldVMOldDisk.vhd" -DestinationPath "D:VMsOldVMOldDisk.vhdx" -VHDType Dynamic

Checkpoints (Snapshots)

Create a checkpoint before making risky changes:

Checkpoint-VM -Name "WebFrontend01" -SnapshotName "Before-IIS-Upgrade-2026-05-17"

List all checkpoints for a VM:

Get-VMCheckpoint -VMName "WebFrontend01"

Restore to a specific checkpoint:

Restore-VMCheckpoint -Name "Before-IIS-Upgrade-2026-05-17" -VMName "WebFrontend01" -Confirm:$false

Remove a checkpoint (frees disk space by merging the differencing disk):

Remove-VMCheckpoint -VMName "WebFrontend01" -Name "Before-IIS-Upgrade-2026-05-17"

Configure checkpoint type — Production checkpoints use VSS inside the guest for application-consistent state:

Set-VM -Name "WebFrontend01" -CheckpointType Production

Exporting and Importing Virtual Machines

Export a VM (creates a complete portable copy including all disks and configuration):

Export-VM -Name "WebFrontend01" -Path "E:Exports"

This creates a folder structure at E:ExportsWebFrontend01 containing the VM configuration and disk files. Import a previously exported VM:

Import-VM -Path "E:ExportsWebFrontend01Virtual Machines{GUID}.vmcx" -Copy -GenerateNewId

Bulk VM Operations with the Pipeline

PowerShell pipelines make bulk operations simple. Start all VMs that are currently saved:

Get-VM | Where-Object { $_.State -eq 'Saved' } | Start-VM

Shut down all running VMs except domain controllers:

Get-VM | Where-Object { $_.State -eq 'Running' -and $_.Name -notlike "DC*" } | Stop-VM

Create checkpoints on all running VMs before a host maintenance window:

Get-VM | Where-Object { $_.State -eq 'Running' } | ForEach-Object {
    Checkpoint-VM -Name $_.Name -SnapshotName "Pre-Maintenance-$(Get-Date -Format 'yyyy-MM-dd')"
    Write-Host "Checkpoint created for $($_.Name)"
}

Report memory usage for all VMs in a formatted table:

Get-VM | Select-Object Name, State, 
    @{N='MemoryGB'; E={[math]::Round($_.MemoryAssigned/1GB, 2)}},
    @{N='MemoryDemandGB'; E={[math]::Round($_.MemoryDemand/1GB, 2)}},
    CPUUsage, Uptime | Format-Table -AutoSize

Hyper-V PowerShell Remoting

Manage Hyper-V on remote hosts by specifying the -ComputerName parameter. This works with most Hyper-V cmdlets and requires WinRM connectivity to the remote host:

Get-VM -ComputerName "HV-HOST-02"

Start a VM on a remote host:

Start-VM -Name "DBServer01" -ComputerName "HV-HOST-02"

Query all VMs across multiple Hyper-V hosts at once:

$hvHosts = @("HV-HOST-01", "HV-HOST-02", "HV-HOST-03")
Get-VM -ComputerName $hvHosts | Select-Object ComputerName, Name, State, MemoryAssigned | Format-Table -AutoSize

Use an Enter-PSSession or Invoke-Command for operations that don’t support -ComputerName:

Invoke-Command -ComputerName "HV-HOST-02" -ScriptBlock {
    Import-Module Hyper-V
    Get-VMNetworkAdapter -VMName "DBServer01"
}

To manage Hyper-V on Server Core or Nano Server hosts remotely from your workstation, ensure the Hyper-V PowerShell tools are installed locally:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Management-PowerShell

Live Migration with PowerShell

Move a running VM to another host (requires shared storage or storage migration):

Move-VM -Name "WebFrontend01" -DestinationHost "HV-HOST-02"

Storage live migration — move VM storage to a different path while the VM is running:

Move-VMStorage -VMName "WebFrontend01" -DestinationStoragePath "E:VMsWebFrontend01"

Move both the VM and its storage simultaneously:

Move-VM -Name "WebFrontend01" -DestinationHost "HV-HOST-02" `
    -IncludeStorage -DestinationStoragePath "D:VMsWebFrontend01"

PowerShell provides the depth of control needed for serious Hyper-V management. Combining these cmdlets with scheduled tasks, monitoring scripts, and CI/CD pipelines gives you a fully automated virtualization platform built on Windows Server 2022.