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​
| Mode | Behavior | Best For |
|---|---|---|
| Static | Fixed memory amount, never changes | Workloads with predictable, constant memory needs |
| Dynamic | Adjusts between min and max based on demand | Variable 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
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​
MinimumBytesmust be <=StartupBytes.StartupBytesmust 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​
- Use dynamic memory for most VMs: It maximizes host density and adapts to workload changes.
- Set realistic minimums: Do not set the minimum below the guest OS’s operational requirement.
- Set maximums based on host capacity: Avoid unrealistic totals that create constant host memory pressure.
- Stop VMs before changing StartupBytes: Changing
StartupBytes(static or dynamic) requires the VM to be powered off. - Monitor memory demand: Use
Get-VM | Select-Object Name, MemoryDemandto 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.