Skip to main content

How to Set Memory for a Hyper-V VM in Batch Script

Memory allocation is one of the most impactful configuration decisions for a virtual machine. Assigning too little memory causes the guest OS to swap heavily, degrading performance dramatically. Assigning too much wastes host resources that could serve other VMs. Hyper-V offers both static and dynamic memory options, and configuring them correctly from a Batch Script enables efficient resource management across your virtual infrastructure.

In this guide, we will explore how to configure memory settings for Hyper-V virtual machines using PowerShell cmdlets within a Batch Script.

Understanding Static vs. Dynamic Memory​

ModeBehaviorBest For
StaticFixed memory amount, never changesWorkloads with predictable, constant memory needs
DynamicAdjusts between min and max based on demandVariable workloads, maximizing host density

Dynamic memory allows Hyper-V to reclaim unused RAM from idle VMs and allocate it to VMs under pressure, improving overall host utilization.

Method 1: Setting Static Memory​

@echo off
setlocal

set "vm_name=WebServer-01"
set "memory_gb=4"

:: Verify Admin
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Administrator privileges required.
pause
exit /b 1
)

echo Setting static memory for "%vm_name%" to %memory_gb% GB...

powershell -NoProfile -Command ^
"try {" ^
" $vm = Get-VM -Name '%vm_name%' -ErrorAction Stop;" ^
" if ($vm.State -ne 'Off') { throw ('VM must be Off for static memory changes. Current state: ' + $vm.State) }" ^
" Set-VMMemory -VMName '%vm_name%' -DynamicMemoryEnabled $false -StartupBytes %memory_gb%GB -ErrorAction Stop;" ^
" Write-Host '[SUCCESS] Memory set.'; exit 0" ^
"} catch { Write-Host ('[ERROR] ' + $_.Exception.Message); exit 1 }"

if %errorlevel%==0 (
echo [SUCCESS] Memory set to %memory_gb% GB (static^).
) else (
echo [ERROR] Failed.
)

pause
info

Static memory changes require the VM to be in the Off state. You cannot change static memory while the VM is running.

Method 2: Configuring Dynamic Memory​

Dynamic memory requires three values: minimum, startup, and maximum.

@echo off
setlocal

set "vm_name=AppServer-01"
set "min_mb=1024"
set "startup_mb=2048"
set "max_mb=8192"

net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Admin required.
pause
exit /b 1
)

echo Configuring dynamic memory for "%vm_name%"...
echo Minimum: %min_mb% MB
echo Startup: %startup_mb% MB
echo Maximum: %max_mb% MB
echo.

powershell -NoProfile -Command ^
"try {" ^
" $vm = Get-VM -Name '%vm_name%' -ErrorAction Stop;" ^
" if ($vm.State -ne 'Off') { throw ('VM should be Off when setting StartupBytes. Current state: ' + $vm.State) }" ^
" Set-VMMemory -VMName '%vm_name%' -DynamicMemoryEnabled $true -ErrorAction Stop " ^
" -MinimumBytes %min_mb%MB -StartupBytes %startup_mb%MB -MaximumBytes %max_mb%MB;" ^
" Write-Host '[SUCCESS] Dynamic memory configured.'; exit 0" ^
"} catch { Write-Host ('[ERROR] ' + $_.Exception.Message); exit 1 }"

if %errorlevel%==0 (
echo [SUCCESS] Dynamic memory configured.
) else (
echo [ERROR] Failed. Ensure the VM is stopped and values are valid.
)

pause

Parameter Rules​

  • MinimumBytes must be <= StartupBytes.
  • StartupBytes must be <= MaximumBytes.
  • Values must be reasonable for the guest OS and host capacity.

Method 3: Viewing Current Memory Configuration​

@echo off
setlocal

set "vm_name=AppServer-01"

net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Admin required.
pause
exit /b 1
)

echo Memory configuration for "%vm_name%":
echo ======================================
echo.

powershell -NoProfile -Command ^
"try {" ^
" $vm = Get-VM -Name '%vm_name%' -ErrorAction Stop;" ^
" $mem = Get-VMMemory -VMName '%vm_name%' -ErrorAction Stop;" ^
" Write-Host (' VM State: {0}' -f $vm.State);" ^
" Write-Host (' Dynamic Memory: {0}' -f $mem.DynamicMemoryEnabled);" ^
" Write-Host (' Startup: {0:N2} GB' -f ($mem.Startup/1GB));" ^
" if ($mem.DynamicMemoryEnabled) {" ^
" Write-Host (' Minimum: {0:N2} GB' -f ($mem.Minimum/1GB));" ^
" Write-Host (' Maximum: {0:N2} GB' -f ($mem.Maximum/1GB));" ^
" Write-Host (' Buffer: {0}%%' -f $mem.Buffer);" ^
" }" ^
" if ($vm.State -eq 'Running') {" ^
" Write-Host (' Assigned: {0:N2} GB' -f ($vm.MemoryAssigned/1GB));" ^
" Write-Host (' Demand: {0:N2} GB' -f ($vm.MemoryDemand/1GB));" ^
" } else {" ^
" Write-Host ' Assigned: N/A (VM not running)';" ^
" Write-Host ' Demand: N/A (VM not running)'" ^
" }" ^
" exit 0" ^
"} catch { Write-Host ('[ERROR] ' + $_.Exception.Message); exit 1 }"

pause

Method 4: Bulk Memory Configuration​

Set memory for multiple VMs at once, useful for standardizing a lab or cluster:

@echo off
setlocal enabledelayedexpansion

net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Admin required.
pause
exit /b 1
)

echo =============================================
echo BULK MEMORY CONFIGURATION
echo =============================================
echo.

:: Define VMs and their memory: name|min_mb|startup_mb|max_mb
set "vm_count=4"
set "vms[0]=WebServer-01|1024|2048|4096"
set "vms[1]=WebServer-02|1024|2048|4096"
set "vms[2]=AppServer-01|2048|4096|8192"
set "vms[3]=SQLServer-01|4096|8192|16384"

set /a last=vm_count - 1
for /L %%i in (0,1,!last!) do (
for /f "tokens=1,2,3,4 delims=|" %%A in ("!vms[%%i]!") do (
echo Configuring %%A: min=%%BMB startup=%%CMB max=%%DMB

powershell -NoProfile -Command ^
"try {" ^
" $vm = Get-VM -Name '%%A' -ErrorAction Stop;" ^
" if ($vm.State -ne 'Off') { throw ('VM must be Off (needed for StartupBytes). State: ' + $vm.State) }" ^
" Set-VMMemory -VMName '%%A' -DynamicMemoryEnabled $true -ErrorAction Stop " ^
" -MinimumBytes %%BMB -StartupBytes %%CMB -MaximumBytes %%DMB;" ^
" Write-Host ' [OK]'; exit 0" ^
"} catch { Write-Host (' [FAIL] ' + $_.Exception.Message); exit 1 }"

if !errorlevel!==0 (
rem already printed [OK] from PowerShell
) else (
rem already printed [FAIL] from PowerShell
)
)
)

echo.
echo [DONE]
pause

Method 5: Interactive Memory Manager​

@echo off
title VM Memory Manager
setlocal enabledelayedexpansion

net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Run as Administrator.
pause
exit /b 1
)

:menu
cls
echo =============================================
echo VM MEMORY MANAGER
echo =============================================
echo.

powershell "-NoProfile -Command " ^
"Get-VM | Sort-Object Name | ForEach-Object {" ^
" $m = Get-VMMemory -VMName $_.Name -ErrorAction SilentlyContinue;" ^
" [PSCustomObject]@{" ^
" Name = $_.Name" ^
" State = $_.State" ^
" AssignedGB = [math]::Round($_.MemoryAssigned/1GB,1)" ^
" DemandGB = [math]::Round($_.MemoryDemand/1GB,1)" ^
" Dynamic = if ($m) { $m.DynamicMemoryEnabled } else { $null }" ^
" }" ^
"} | Format-Table -AutoSize"

echo.
set /p "vm_name=Enter VM name to configure (or EXIT): "
if /i "!vm_name!"=="EXIT" exit /b 0

echo.
echo [1] Set static memory
echo [2] Set dynamic memory
echo [3] View current config
set /p "choice=Select: "

if "!choice!"=="1" (
set /p "mem=Enter memory in GB: "
powershell "-NoProfile -Command" ^
"try {" ^
" $vm = Get-VM -Name '!vm_name!' -ErrorAction Stop;" ^
" if ($vm.State -ne 'Off') { throw ('VM must be Off. State: ' + $vm.State) }" ^
" Set-VMMemory -VMName '!vm_name!' -DynamicMemoryEnabled $false -StartupBytes !mem!GB -ErrorAction Stop;" ^
" Write-Host '[OK] Static memory set.'; exit 0" ^
"} catch { Write-Host ('[ERROR] ' + $_.Exception.Message); exit 1 }"
pause
goto menu
)

if "!choice!"=="2" (
set /p "min=Minimum (MB): "
set /p "start=Startup (MB): "
set /p "max=Maximum (MB): "
powershell -NoProfile -Command ^
"try {" ^
" $vm = Get-VM -Name '!vm_name!' -ErrorAction Stop;" ^
" if ($vm.State -ne 'Off') { throw ('VM must be Off to set StartupBytes. State: ' + $vm.State) }" ^
" Set-VMMemory -VMName '!vm_name!' -DynamicMemoryEnabled $true -ErrorAction Stop " ^
" -MinimumBytes !min!MB -StartupBytes !start!MB -MaximumBytes !max!MB;" ^
" Write-Host '[OK] Dynamic memory configured.'; exit 0" ^
"} catch { Write-Host ('[ERROR] ' + $_.Exception.Message); exit 1 }"
pause
goto menu
)

if "!choice!"=="3" (
powershell -NoProfile -Command ^
"try { Get-VMMemory -VMName '!vm_name!' -ErrorAction Stop | Format-List *; exit 0 }" ^
"catch { Write-Host ('[ERROR] ' + $_.Exception.Message); exit 1 }"
pause
goto menu
)

goto menu

Setting the Memory Buffer Percentage​

The memory buffer is extra memory Hyper-V keeps allocated above the VM's actual demand. The default is 20%.

@echo off
setlocal

set "vm_name=WebServer-01"
set "buffer=30"

net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Admin required.
pause
exit /b 1
)

powershell -NoProfile -Command ^
"try { Set-VMMemory -VMName '%vm_name%' -Buffer %buffer% -ErrorAction Stop; exit 0 }" ^
"catch { Write-Host ('[ERROR] ' + $_.Exception.Message); exit 1 }"

if %errorlevel%==0 (
echo [OK] Memory buffer set to %buffer%%% for %vm_name%.
) else (
echo [ERROR] Failed to set memory buffer.
)

pause

A buffer of 20–30% is common. Higher buffers provide more headroom for sudden memory spikes but reduce the amount of RAM available for other VMs.

Common Mistakes​

The Wrong Way: Setting Memory While VM Is Running (Static Mode)​

:: WRONG - Static memory changes require the VM to be stopped
powershell -Command "Set-VMMemory -VMName 'RunningVM' -DynamicMemoryEnabled $false -StartupBytes 8GB"

Output Concern: Changing from dynamic to static mode, or changing the startup memory value in static mode, requires the VM to be in the Off state. The command will fail with an error if the VM is running. Dynamic memory min/max adjustments can sometimes be applied while running, but changing StartupBytes still requires the VM to be off.

The Wrong Way: Setting Minimum Higher Than Startup​

:: WRONG - Minimum cannot exceed startup
powershell -Command "Set-VMMemory -VMName 'MyVM' -MinimumBytes 4GB -StartupBytes 2GB -MaximumBytes 8GB"

The command will fail because MinimumBytes (4 GB) is greater than StartupBytes (2 GB). The correct relationship is: Minimum <= Startup <= Maximum.

Best Practices​

  1. Use dynamic memory for most VMs: It maximizes host density and adapts to workload changes.
  2. Set realistic minimums: Do not set the minimum below the guest OS’s operational requirement.
  3. Set maximums based on host capacity: Avoid unrealistic totals that create constant host memory pressure.
  4. Stop VMs before changing StartupBytes: Changing StartupBytes (static or dynamic) requires the VM to be powered off.
  5. Monitor memory demand: Use Get-VM | Select-Object Name, MemoryDemand to identify VMs that consistently need more memory.

Conclusion​

Setting memory for Hyper-V virtual machines from a Batch Script is handled by PowerShell’s Set-VMMemory cmdlet. Static memory provides predictable allocation for performance-sensitive workloads, while dynamic memory enables efficient resource sharing across many VMs. By configuring appropriate minimum, startup, and maximum values with a reasonable buffer percentage, administrators can optimize both individual VM performance and overall host utilization. Bulk configuration scripts ensure consistent memory policies across entire virtual environments.