Hyper-V Cheatsheet
TL;DR commands, snippets, and functions that I use quite a bit while creating and configuring VMs and managing Hyper-V.
Welcome to Part XI of our cheatsheet series compiled from various courses, labs, stuff we did at work, Google, etc. Most of this was spread out over various howtos. This puts it all in one place. These are cheatsheets, almost no explanation is given, just commands. The links are to howtos that provide background.
Part I: Mimikatz cheatsheet
Part II: Set-Acl cheatsheet
Part III: Get-Acl cheatsheet
Part IV: Enumerating AD cheatsheet
Part V: Windows reverse shells cheatsheet
Part VI: MS Graph PowerShell cheatsheet
Part VII: Hash cracking cheatsheet
Part VIII: The Credential Theft Shuffle
Part IX: SACLs & Querying Collected Logs
Part X: Setting up a simple AD lab in Azure
Part XI: Hyper-V cheatsheet
Part XII: Migrating to openSUSE LEAP
Part XIII: Automating VM creation in ESXi with PowerCLI
Part XIV: PowerCLI cheatsheet
Part XV: Automating VM creation in ESXi with Ansible
Background
I had been meaning to make a Hyper-V cheatsheet for awhile. There’s other cheatsheets out there on Google, but a lot of them are just ‘New-VMSwitch’ without much context or how to automate putting that vSW on a physical NIC and allowing the host OS to use the NIC as well. IMHO that’s not all that helpful, after all the commands themselves are well documented on Microsoft Learn.
This cheatsheet is snippets, small functions, and a few queries with somewhat complex syntax that I use on a regular basis to create and configure VMs, as well as query info related to them.
I am a big fan of Hyper-V, and to an extant Azure, and freely admit my bias here. I was not a fan of VMware even before Broadcom bought them as their version of PowerShell Direct, PowerCLI, was never free and hence was not usable with the free version of ESXi.
By contrast not only is Hyper-V itself free, all its features are free. Hyper-V is after all a Microsoft product, not an open source creation of Linus Torvalds or Richard Stallman. Hyper-V, PowerShell Core, and others like them are why I think of Microsoft today, in 2025, as a midpoint between open source and hyper proprietary orgs like Apple. Microsoft today isn’t perfect, but they’re a LOT better than long ago Steve Ballmer’s “open source is cancer” version. Today they have more employees working on open source than Red Hat does. They’re #2 on that list, and not far behind Google.
Bill Gate’s “Open Letter to Hobbyists” was a long, long time ago. Microsoft turned the ship around, and I’m very happy they did. I didn’t like or trust the old Microsoft.
Creating vSWs, VMs, etc
This is a snippet from my function that automates creating VMs using an ISO, an answer file, and Convert-WindowsImage.
#Find the active NIC, create a new vSW, and map to the active NIC
$NIC = Get-NetAdapter | Where-Object {($_.Name -like "Ethernet*") -and ($_.Status -eq "Up")}
New-VMSwitch -Name "Testing" -NetAdapterName "$NIC" ; Set-VMSwitch -Name Testing -AllowManagementOS $true
#Create a VM, set it's RAM, and connect it to a vSW
New-VM -Name $VMName -Path "C:\Hyper-V_VMs\$VMName" -MemoryStartupBytes 6GB -Generation 2
Set-VMMemory -VMName $VMName -DynamicMemoryEnabled $true -MinimumBytes 6GB -StartupBytes 6GB -MaximumBytes 8GB
Connect-VMNetworkAdapter -VMName $VMName -Name "Network Adapter" -SwitchName "Testing"
#https://github.com/x0nn/Convert-WindowsImage
Install-Module -Name Convert-WindowsImage
$isoFilePath = "C:\VM_Stuff_Share\ISOs\Windows Server 2022 (20348.169.210806–2348.fe_release_svc_refresh_SERVER_EVAL_x64FRE_en-us).iso"
$answerFilePath = "C:\VM_Stuff_Share\New_VM\2022_autounattend.xml"
New-Item -ItemType Directory -Path C:\Hyper-V_VMs\$VMName
$convertParams = @{
SourcePath = $isoFilePath
SizeBytes = 100GB
Edition = 'Windows Server 2022 Datacenter Evaluation (Desktop Experience)'
VHDFormat = 'VHDX'
VHDPath = "C:\Hyper-V_VMs\$VMName\$VMName.vhdx"
DiskLayout = 'UEFI'
UnattendPath = $answerFilePath
}
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser
. "C:\VM_Stuff_Share\Convert-WindowsImage (from PS Gallery)\Convert-WindowsImage.ps1"
Convert-WindowsImage @convertParams
#Connect a HD to the VM, set the bootorder, and bootup the VM
$vm = Get-Vm -Name $VMName
$vm | Add-VMHardDiskDrive -Path "C:\Hyper-V_VMs\$VMName\$VMName.vhdx"
$bootOrder = ($vm | Get-VMFirmware).Bootorder
if ($bootOrder[0].BootType -ne 'Drive')
{
$vm | Set-VMFirmware -FirstBootDevice $vm.HardDrives[0]
}
Start-VM -Name $VMNameOperations on VMs
The ability to easily automate uploading files to the VM is one of the nice, free features in Hyper-V. I used this feature pretty heavily in Mishky’s AD Range for everything from uploading a CSV of users to create to populating the share drive.
#Check what guest services are enabled on a VM
Get-VMIntegrationService -VMName "VM Name"
#Enable the service that allows uploading files to VMs and upload a file to a VM
Enable-VMIntegrationService "Guest Service Interface" -VMName "Research-DC"
Copy-VMFile "Research-DC" -SourcePath ".\HTTPsCertificates.json" -DestinationPath "C:\HTTPsCertificates.json" -CreateFullPath -FileSource Host
# Create a checkpoint on the host
Checkpoint-VM -Name "Shop-Client" -SnapshotName "BeforePublish_$(Get-Date -Format yyyyMMdd_HHmm)"
#Verify a snapshot
Get-VMSnapshot -VMName "Name"
#Restore a snapshot
Restore-VMSnapshot -Name "Name" -VMName "VM Name" -Confirm:$falsePowerShell Direct
Get Rich’s stories in your inbox
Join Medium for free to get updates from this writer.
This free Hyper-V feature is clutch. As mentioned earlier, VMware has PowerCLI, but it’s not included for free. Great, free features in Hyper-V are why I was running with the wind and automating things within the first week of trying it out, things I was never able to do at all in ESXi.
#This password comes from the *.xml answer file used to create the VM's HD
#VM's initial local admin:
[string]$userName = "Changme\Administrator"
[string]$userPassword = 'SuperSecureLocalPassword123!@#'
# Convert to SecureString
[securestring]$secStringPassword = ConvertTo-SecureString $userPassword -AsPlainText -Force
[pscredential]$InitialCredObject = New-Object System.Management.Automation.PSCredential ($userName, $secStringPassword)
#Run commands on the VM via PowerShell Direct
Invoke-Command -VMName "ShopDC" {$env:USERNAME ; $env:COMPUTERNAME} -Credential $InitialCredObject
#Run multiple commands/lines via PowerShell Direct
Invoke-Command -VMName "ShopDC" -Credential $InitialCredObject -ScriptBlock {
$env:USERNAME
$env:USERDOMAIN
$env:COMPUTERNAME
}
#Run a PS1 on the VM
Invoke-Command -VMName "Shop-DC" -FilePath '.\VMConfig (ShopDC P1).ps1' -Credential $InitialCredObject #Configs IPv4, disables IPv6, renames the VMPassing variables from Hyper-V to a VM
I used this heavily in ‘Config-NIC’ to capture variables like the Gateway, Prefix, IP scheme, DNS Servers, etc and then configure VMs accordingly.
#Use $using:VariableName
$X = 2
$Y = 5
Invoke-Command -VMName "Shop-DC" {$using:X + $using:Y} -Credential $InitialCredObject
#Note this isn't just for VMs via PowerShell Direct, you can passvariables to another domain system this way too
Invoke-Command "TestDC" {$using:X + $using:Y}
#This is insanely useful for capturing things in a variable on the hypervisor itself or one VM, then re-using that variable on a different VMOperations on Hyper-V itself
Here’s a few more things I was never able to do in ESXi. Even at work, where we license it for now, doing this was rather annoying and migraine inducing.
#Live migrate a VM
$VMName = "BackupDC"
Move-VM -Name $VMName -DestinationHost ServerI -IncludeStorage -DestinationStoragePath C:\Hyper-V_VMs\$VMName
#Confirm migration
Get-VM -ComputerName ServerI, ServerII | Select-Object ComputerName, Name, State, CPUUsage, MemoryAssigned, Uptime, Status | Format-Table
#Enable metering on all VMs
Get-VM -ComputerName ServerI, ServerII | Enable-VMResourceMetering
#Get stats, good for checking average RAM, CPU, network usage over time
Get-VM -ComputerName ServerI, ServerII | Measure-VM
#Show VM stats on multiple Hyper-V hosts
Get-VM -ComputerName ServerI, ServerII | Select-Object ComputerName, Name, State, CPUUsage, @{Name="RAMAssigned(GBs)";Expression={ [math]::Round($_.MemoryAssigned / 1GB, 2) }}, @{Name="Uptime(Days, Hours, Mins)";Expression={$_.Uptime.Days,$_.Uptime.Hours, $_.Uptime.Minutes }}, Status, @{Name="HD Size(GBs)";Expression={ [math]::round((Get-VM -ComputerName ServerI, ServerII -Name $_.Name | Select-Object -Property VMId | Get-VHD -ComputerName $_.ComputerName).FileSize /1GB, 2) }} | Format-Table -AutoSizeRandom PowerShell Stuff
Ironically looking up the difference between ‘Get-History’ and ‘Get-Content ConsoleHost_history.txt’ was what I was doing when the original ServerII bought the farm.
#Get entire PowerShell history
Get-Content (Get-PSReadLineOption).HistorySavePath
#Read PowerShell persistent history
Get-Content "C:\Users\$env:USERNAM\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt"
#Get current session's history. PowerShell_ISE does't save persistent history
Get-History
history
#Get free HD space on multiple Hyper-V Server 2019s or Server Cores
Get-CimInstance -ComputerName ServerI, ServerII Win32_LogicalDisk | Where-Object DriveType -eq 3 | Select-Object PSComputerName, DeviceID, @{Name="Total Space (GB)"; Expression={[math]::Round($_.Size/1GB, 2)}}, @{Name="Used Space (GB)"; Expression={[math]::Round(($_.Size - $_.FreeSpace)/1GB, 2)}}, @{Name="Free Space (GB)"; Expression={[math]::Round($_.FreeSpace/1GB, 2)}} | Format-Table -AutoSizeThis works fine when you only have two hypervisors, but what if you’re a larger organization?
We can scale this query by pulling an entire OU and then using ‘ForEach-Object’.
I only have two hypervisors in test.local and they’re not in a separate OU. They probably should be, but that’s another project for the future. Right now they’re in the ‘Member Severs’ OU along with our WEC, Entra Connect, etc servers.
Hence I used the Domain Controllers OU as an example.
$ADRoot = (Get-ADDomain).DistinguishedName
$OUPath = "OU=Domain Controllers,$ADRoot"
(Get-ADComputer -Filter * -SearchBase $OUPath).Name | ForEach-Object {Get-CimInstance -ComputerName $_ Win32_LogicalDisk | Where-Object DriveType -eq 3 | Select-Object PSComputerName, DeviceID, @{Name="Total Space (GB)"; Expression={[math]::Round($_.Size/1GB, 2)}}, @{Name="Used Space (GB)"; Expression={[math]::Round(($_.Size - $_.FreeSpace)/1GB, 2)}}, @{Name="Free Space (GB)"; Expression={[math]::Round($_.FreeSpace/1GB, 2)}}} | Format-Table -AutoSizeSummary
This right here is why I post these cheatsheets. In a year from now I won’t remember how I automated querying the used HD space on an entire OU of VMs … but I don’t have to. I can go back, check this, and copy/paste.
I really only memorize things that will be on an exam I’m about to take, for example I memorized an nmap cheatsheet before I took CEH. Other than that I make cheatsheets and then reference them.
I say that the target audience of what I post on Medium is system administrators, auditors, cyber folks, etc … but the real intended audience is me in a year or two. I go back and check these all the time. For example I was pushing an agent for a cyber tool via GPO at work recently and I referenced something I posted 4 years ago.
References
Hyper-V PowerShell Module: https://learn.microsoft.com/en-us/powershell/module/hyper-v/?view=windowsserver2025-ps
Top org contributors to open source: https://opensourceindex.io/
Bill Gates Open Letter to Hobbyists: https://en.wikipedia.org/wiki/An_Open_Letter_to_Hobbyists
Migrate VMs from Hyper-V to Azure: https://learn.microsoft.com/en-us/azure/migrate/tutorial-migrate-hyper-v?view=migrate&tabs=UI
BackupChain’s Hyper-V cheatsheet: https://hyper-v-backup.backupchain.com/the-ultimate-hyper-v-powershell-commands-cheat-sheet/







