Skip to main content

How to Create a Snapshot (Checkpoint) of a Hyper-V VM in Batch Script

Checkpoints (formerly called snapshots) capture the entire state of a virtual machine at a specific point in time, including disk contents, memory state, and configuration. They provide an instant rollback mechanism that is invaluable before applying updates, testing configuration changes, or performing any risky operation on a VM. If something goes wrong, you can revert to the checkpoint in seconds.

In this guide, we will explore how to create Hyper-V checkpoints from a Batch Script using PowerShell, including standard and production checkpoints, naming conventions, and automated pre-change workflows.

Understanding Checkpoint Types

Hyper-V offers two checkpoint types:

TypeContentsUse Case
StandardDisk state + memory state + device stateDevelopment, testing, labs
ProductionDisk state only (uses VSS/filesystem freeze)Production servers
  • Standard checkpoints capture everything, including running applications in memory. They are ideal for development because restoring resumes exactly where you left off.
  • Production checkpoints use Volume Shadow Copy (Windows) or filesystem freeze (Linux) to create an application-consistent disk snapshot. They do not capture memory state but are safe for production workloads like databases.

Method 1: Creating a Basic Checkpoint

@echo off
setlocal

set "vm_name=WebServer-01"

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

echo Creating checkpoint for "%vm_name%"...

powershell -NoProfile -Command "Checkpoint-VM -Name '%vm_name%' -SnapshotName 'Manual Checkpoint'"

if %errorlevel% equ 0 (
echo [SUCCESS] Checkpoint created for "%vm_name%".
) else (
echo [ERROR] Failed to create checkpoint.
)

pause
endlocal

Method 2: Creating a Named and Timestamped Checkpoint

Descriptive checkpoint names make it easy to identify the purpose and timing of each snapshot.

@echo off
setlocal enabledelayedexpansion

set "vm_name=DatabaseVM"

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

:: Build a timestamped name
for /f "tokens=2 delims==" %%T in ('wmic os get LocalDateTime /value') do set "dt=%%T"
set "timestamp=!dt:~0,4!-!dt:~4,2!-!dt:~6,2!_!dt:~8,2!!dt:~10,2!"

:: Optional: include a description
set "desc="
set /p "desc=Enter checkpoint description (or press Enter for default): "
if not defined desc set "desc=Manual Checkpoint"

set "cp_name=!desc! [!timestamp!]"

echo Creating checkpoint: !cp_name!

powershell -NoProfile -Command "Checkpoint-VM -Name '%vm_name%' -SnapshotName '!cp_name!'"

if !errorlevel! equ 0 (
echo [SUCCESS] Checkpoint created.
) else (
echo [ERROR] Failed.
)

pause
endlocal

Method 3: Pre-Change Checkpoint (Automated Safety Net)

The most practical pattern is creating a checkpoint automatically before any maintenance operation.

@echo off
setlocal enabledelayedexpansion

set "vm_name=AppServer-01"

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

echo =============================================
echo PRE-CHANGE CHECKPOINT WORKFLOW
echo =============================================
echo.

:: Step 1: Create a pre-change checkpoint
for /f "tokens=2 delims==" %%T in ('wmic os get LocalDateTime /value') do set "dt=%%T"
set "cp_name=Pre-Update [!dt:~0,4!-!dt:~4,2!-!dt:~6,2! !dt:~8,2!:!dt:~10,2!]"

echo [1/3] Creating checkpoint: !cp_name!
powershell -NoProfile -Command "Checkpoint-VM -Name '%vm_name%' -SnapshotName '!cp_name!'"

if !errorlevel! neq 0 (
echo [ABORT] Checkpoint creation failed. Not proceeding.
pause
exit /b 1
)

echo Checkpoint saved.
echo.

:: Step 2: Perform the maintenance (example: copy update files)
echo [2/3] Performing maintenance...
echo (Your maintenance commands go here^)
timeout /t 3 /nobreak >nul
echo Maintenance complete.
echo.

:: Step 3: Verify and report
echo [3/3] Verifying...
echo If something went wrong, restore with:
echo Restore-VMCheckpoint -VMName "%vm_name%" -Name "!cp_name!" -Confirm:$false
echo.
echo =============================================
echo WORKFLOW COMPLETE
echo =============================================

pause
endlocal

Method 4: Creating Checkpoints for All Running VMs

Before a host-level operation (OS updates, driver changes), checkpoint every running VM.

@echo off
setlocal enabledelayedexpansion

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

for /f "tokens=2 delims==" %%T in ('wmic os get LocalDateTime /value') do set "dt=%%T"
set "cp_name=Pre-Host-Maintenance [!dt:~0,4!-!dt:~4,2!-!dt:~6,2!]"

echo Creating checkpoints for all running VMs...
echo Checkpoint name: !cp_name!
echo.

set "count=0"
set "failed=0"

for /f "delims=" %%N in ('powershell -NoProfile -Command "Get-VM | Where-Object State -eq 'Running' | Select-Object -ExpandProperty Name"') do (
echo Checkpointing %%N...
powershell -NoProfile -Command "Checkpoint-VM -Name '%%N' -SnapshotName '!cp_name!'"

if !errorlevel! equ 0 (
echo [OK]
set /a "count+=1"
) else (
echo [FAIL]
set /a "failed+=1"
)
)

echo.
if !count! equ 0 if !failed! equ 0 (
echo [INFO] No running VMs found.
) else (
echo [DONE] Checkpointed: !count!, Failed: !failed!
)

pause
endlocal

Method 5: Setting the Checkpoint Type

Configure whether a VM uses standard or production checkpoints.

@echo off
setlocal enabledelayedexpansion

set "vm_name=ProductionDB"

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

echo Current checkpoint type for %vm_name%:
powershell -NoProfile -Command "(Get-VM -Name '%vm_name%' -ErrorAction SilentlyContinue).CheckpointType"

echo.
echo [1] Standard - Full state capture (dev/test^)
echo [2] Production - Application-consistent (production^)
echo [3] Disabled - No checkpoints allowed
echo [0] Cancel
echo.
set "choice="
set /p "choice=Select type: "

if "!choice!" == "1" (
powershell -NoProfile -Command "Set-VM -Name '%vm_name%' -CheckpointType Standard"
if !errorlevel! equ 0 (echo [OK] Set to Standard.) else (echo [ERROR] Failed.)
) else if "!choice!" == "2" (
powershell -NoProfile -Command "Set-VM -Name '%vm_name%' -CheckpointType Production"
if !errorlevel! equ 0 (echo [OK] Set to Production.) else (echo [ERROR] Failed.)
) else if "!choice!" == "3" (
powershell -NoProfile -Command "Set-VM -Name '%vm_name%' -CheckpointType Disabled"
if !errorlevel! equ 0 (echo [OK] Checkpoints disabled.) else (echo [ERROR] Failed.)
) else if "!choice!" == "0" (
echo [CANCELLED]
) else (
echo [ERROR] Invalid selection.
)

pause
endlocal
tip

For database servers and other stateful applications, always use Production checkpoints. Standard checkpoints capture in-memory state, which can leave databases in an inconsistent state when restored.

Listing Existing Checkpoints

@echo off
setlocal

set "vm_name=WebServer-01"

echo Checkpoints for %vm_name%:
echo ============================
echo.

powershell -NoProfile -Command ^
"Get-VMCheckpoint -VMName '%vm_name%' -ErrorAction SilentlyContinue |" ^
"Format-Table Name, CreationTime, SnapshotType -AutoSize"

pause
endlocal

Common Mistakes

The Wrong Way: Too Many Checkpoints

:: WRONG - Creating checkpoints without a cleanup strategy
:: Each checkpoint creates differencing disks that consume growing disk space
powershell -Command "Checkpoint-VM -Name 'MyVM' -SnapshotName 'Quick Save'"
:: ... days later, 50 checkpoints exist, disk is full

Output Concern: Every checkpoint creates a differencing disk (.avhdx) that records all changes since the checkpoint was taken. Over time, these files grow large and degrade VM performance due to the I/O overhead of traversing the differencing disk chain. Always implement a retention policy and delete old checkpoints.

The Wrong Way: Using Standard Checkpoints on Production Databases

:: WRONG - Standard checkpoints capture memory state
:: Restoring captures in-flight transactions in an inconsistent state
powershell -Command "Set-VM -Name 'SQLServer' -CheckpointType Standard"

Standard checkpoints capture database memory buffers mid-transaction. Restoring this state can corrupt the database. Use Production checkpoints for any VM running a database or transactional application.

Best Practices

  1. Name checkpoints descriptively: Include the purpose and timestamp (e.g., "Pre-Windows-Update [2024-01-15]").
  2. Use Production checkpoints for production VMs: They create application-consistent snapshots via VSS.
  3. Delete old checkpoints: Implement a retention policy. Never keep more than 3-5 active checkpoints per VM.
  4. Checkpoint before risky operations: Always create a checkpoint before updates, configuration changes, or software installations.
  5. Monitor disk space: Differencing disks from checkpoints can grow rapidly. Monitor the VHDX storage location.

Conclusion

Creating Hyper-V checkpoints from a Batch Script is accomplished through PowerShell's Checkpoint-VM cmdlet. By adding descriptive names, timestamps, and integrating checkpoint creation into pre-change workflows, administrators build reliable safety nets that enable instant rollback when maintenance goes wrong. Choosing the correct checkpoint type (Standard vs. Production) ensures data consistency for the workload type, while bulk checkpoint operations provide host-level protection before major infrastructure changes.