How to Get the Status of All Hyper-V VMs in Batch Script
Monitoring the status of virtual machines is a daily routine for Hyper-V administrators. Knowing which VMs are running, stopped, saved, or in an error state at a glance is essential for capacity planning, incident response, and ensuring that critical services are online. A quick status query replaces the need to open Hyper-V Manager and visually scan through potentially dozens of VMs.
In this guide, we will explore how to retrieve and display the status of all Hyper-V virtual machines from a Batch Script using PowerShell, from basic state summaries to comprehensive health dashboards.
Method 1: Quick Status Overview
The simplest query shows each VM's name, state, CPU usage, and memory allocation.
@echo off
setlocal
echo =============================================
echo HYPER-V VM STATUS
echo %date% %time:~0,8%
echo =============================================
echo.
powershell -NoProfile -Command ^
"Get-VM | Sort-Object State, Name | Format-Table Name, State, CPUUsage," ^
"@{Name='MemGB';Expression={[math]::Round($_.MemoryAssigned/1GB,1)}}," ^
"@{Name='Uptime';Expression={$_.Uptime.ToString('dd\.hh\:mm\:ss')}} -AutoSize"
pause
Sample Output
Name State CPUUsage MemGB Uptime
---- ----- -------- ----- ------
DomainController Running 1 2.0 05.12:30:45
WebServer-01 Running 8 4.0 05.12:30:40
SQLServer-01 Running 15 8.0 05.12:30:38
DevEnvironment Off 0 0.0 00.00:00:00
TestVM-Saved Saved 0 0.0 00.00:00:00
Method 2: Status Summary with Counts
A high-level summary showing how many VMs are in each state:
@echo off
setlocal
echo Hyper-V Status Summary:
echo =======================
echo.
powershell -NoProfile -Command ^
"$vms = Get-VM;" ^
"$total = $vms.Count;" ^
"$running = @($vms | Where-Object State -eq 'Running').Count;" ^
"$off = @($vms | Where-Object State -eq 'Off').Count;" ^
"$saved = @($vms | Where-Object State -eq 'Saved').Count;" ^
"$paused = @($vms | Where-Object State -eq 'Paused').Count;" ^
"$other = $total - $running - $off - $saved - $paused;" ^
"Write-Host (' Running: {0}' -f $running);" ^
"Write-Host (' Off: {0}' -f $off);" ^
"Write-Host (' Saved: {0}' -f $saved);" ^
"Write-Host (' Paused: {0}' -f $paused);" ^
"if ($other -gt 0) { Write-Host (' Other: {0}' -f $other) };" ^
"Write-Host ' -------';" ^
"Write-Host (' Total: {0}' -f $total)"
pause
Method 3: Detailed Health Report
A comprehensive report including CPU, memory, disk, network, and checkpoint information:
@echo off
setlocal
echo Generating detailed VM health report...
echo.
powershell -NoProfile -Command ^
"Get-VM | Sort-Object State, Name | ForEach-Object {" ^
" $icon = switch ($_.State) { 'Running' {'[*]'} 'Off' {'[ ]'} 'Saved' {'[S]'} default {'[?]'} };" ^
" $color = if ($_.State -eq 'Running') {'Green'} else {'Gray'};" ^
" Write-Host ('{0} {1}' -f $icon, $_.Name) -ForegroundColor $color;" ^
" Write-Host (' State: {0}' -f $_.State);" ^
" Write-Host (' CPUs: {0} ({1}%% usage)' -f $_.ProcessorCount, $_.CPUUsage);" ^
" Write-Host (' Memory: {0} GB assigned' -f [math]::Round($_.MemoryAssigned/1GB,2));" ^
" Write-Host (' Uptime: {0}' -f $_.Uptime);" ^
" Write-Host (' Generation: {0}' -f $_.Generation);" ^
" $cpCount = @(Get-VMCheckpoint -VMName $_.Name -ErrorAction SilentlyContinue).Count;" ^
" Write-Host (' Checkpoints: {0}' -f $cpCount);" ^
" foreach ($hd in $_.HardDrives) {" ^
" $file = Get-Item $hd.Path -ErrorAction SilentlyContinue;" ^
" $sizeGB = if ($file) { [math]::Round($file.Length/1GB,2) } else { 'N/A' };" ^
" Write-Host (' Disk: {0} ({1} GB)' -f $hd.Path, $sizeGB)" ^
" };" ^
" foreach ($nic in $_.NetworkAdapters) {" ^
" Write-Host (' Network: {0}' -f $nic.SwitchName)" ^
" };" ^
" Write-Host ''" ^
"}"
pause
Method 4: Live Monitoring Dashboard
A self-refreshing dashboard that updates every few seconds:
@echo off
title Hyper-V Status Monitor
:loop
cls
echo =============================================
echo HYPER-V LIVE MONITOR
echo %date% %time:~0,8%
echo =============================================
echo.
powershell -NoProfile -Command ^
"$vms = Get-VM | Sort-Object State, Name;" ^
"$running = @($vms | Where-Object State -eq 'Running');" ^
"$off = @($vms | Where-Object State -eq 'Off');" ^
"$totalCPU = ($running | Measure-Object CPUUsage -Sum).Sum;" ^
"$totalMem = ($running | Measure-Object MemoryAssigned -Sum).Sum / 1GB;" ^
"Write-Host (' VMs: {0} Running / {1} Off / {2} Total' -f $running.Count, $off.Count, $vms.Count);" ^
"Write-Host (' CPU: {0}%% total usage' -f $totalCPU);" ^
"Write-Host (' RAM: {0:N1} GB total assigned' -f $totalMem);" ^
"Write-Host '';" ^
"Write-Host ' Name State CPU Memory Uptime';" ^
"Write-Host ' ---- ----- --- ------ ------';" ^
"$vms | ForEach-Object {" ^
" $icon = if ($_.State -eq 'Running') {'*'} else {' '};" ^
" Write-Host (' [{0}] {1,-23} {2,-9} {3,3}%% {4,6:N1} GB {5}' -f" ^
" $icon, $_.Name, $_.State, $_.CPUUsage," ^
" [math]::Round($_.MemoryAssigned/1GB,1)," ^
" $_.Uptime.ToString('dd\.hh\:mm'))" ^
"}"
echo.
echo Refreshing in 10 seconds. Press Ctrl+C to stop.
timeout /t 10 /nobreak >nul
goto loop
Method 5: CSV Export for Reporting
Generate a CSV file for inventory management or compliance reports:
@echo off
setlocal
for /f "tokens=2 delims==" %%T in ('wmic os get LocalDateTime /value') do set "dt=%%T"
set "stamp=%dt:~0,4%%dt:~4,2%%dt:~6,2%"
set "output=%~dp0hyperv_status_%COMPUTERNAME%_%stamp%.csv"
echo Exporting VM status to CSV...
powershell -NoProfile -Command ^
"Get-VM | Select-Object Name, State," ^
"@{Name='CPUCount';Expression={$_.ProcessorCount}}," ^
"@{Name='CPUUsage';Expression={$_.CPUUsage}}," ^
"@{Name='MemoryGB';Expression={[math]::Round($_.MemoryAssigned/1GB,2)}}," ^
"@{Name='Uptime';Expression={$_.Uptime.ToString()}}," ^
"Generation," ^
"@{Name='Checkpoints';Expression={@(Get-VMCheckpoint -VMName $_.Name -ErrorAction SilentlyContinue).Count}}," ^
"@{Name='DiskPaths';Expression={($_.HardDrives.Path) -join '; '}}," ^
"@{Name='Switches';Expression={($_.NetworkAdapters.SwitchName) -join '; '}}" ^
"| Export-Csv -Path '%output%' -NoTypeInformation"
if %errorlevel%==0 (
echo [SUCCESS] Exported to: %output%
echo.
type "%output%"
) else (
echo [ERROR] Export failed.
)
echo.
pause
Host Resource Summary
Beyond individual VM status, understanding host-level resource utilization is important:
@echo off
echo.
echo =============================================
echo HOST RESOURCE SUMMARY
echo =============================================
echo.
powershell -NoProfile -Command ^
"$hi = Get-VMHost;" ^
"$vms = Get-VM;" ^
"$running = @($vms | Where-Object State -eq 'Running');" ^
"$totalAssigned = ($running | Measure-Object MemoryAssigned -Sum).Sum / 1GB;" ^
"$totalStorage = 0;" ^
"foreach ($hd in $vms.HardDrives) {" ^
" $file = Get-Item $hd.Path -ErrorAction SilentlyContinue;" ^
" if ($file) { $totalStorage += $file.Length }" ^
"};" ^
"$totalStorageGB = $totalStorage / 1GB;" ^
"Write-Host (' Logical Processors: {0}' -f $hi.LogicalProcessorCount);" ^
"Write-Host (' VM Path: {0}' -f $hi.VirtualMachinePath);" ^
"Write-Host (' VHD Default Path: {0}' -f $hi.VirtualHardDiskPath);" ^
"Write-Host (' Running VMs: {0}' -f $running.Count);" ^
"Write-Host (' Total RAM Assigned: {0:N1} GB' -f $totalAssigned);" ^
"Write-Host (' Total Disk Used: {0:N1} GB' -f $totalStorageGB)"
pause
Common Mistakes
The Wrong Way: Using WMIC for VM Status
:: WRONG - WMI queries for Hyper-V are complex and poorly documented
wmic /namespace:\\root\virtualization\v2 path Msvm_ComputerSystem get ElementName,EnabledState
Output Concern:
While the WMI path works, the EnabledState values are numeric codes (2=Running, 3=Off) that must be manually decoded. Get-VM returns human-readable state names and far more information with simpler syntax.
The Wrong Way: Not Running as Administrator
:: WRONG - Returns empty or partial results without elevation
powershell -Command "Get-VM"
Get-VM requires administrator privileges. Without elevation, it may return no results or throw access denied errors. Always verify admin rights before querying.
Best Practices
- Use
Get-VMfor all status queries: It is the official, comprehensive, and human-readable interface. - Sort by state: Show running VMs first for quick identification of active workloads.
- Include resource metrics: CPU usage and memory allocation reveal overloaded or underutilized VMs.
- Export regularly: CSV exports create audit trails and support capacity planning analysis.
- Monitor checkpoint counts: Excessive checkpoints degrade performance and consume storage.
Conclusion
Getting the status of all Hyper-V VMs from a Batch Script is powered by PowerShell's Get-VM cmdlet, which provides comprehensive information about each virtual machine's state, resource usage, and configuration. From quick one-line status checks to full health dashboards with live refresh, the patterns in this guide enable administrators to maintain continuous visibility into their virtual infrastructure. Regular CSV exports and host resource summaries complete the monitoring toolkit for professional Hyper-V management.