Skip to content

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

Learn how to automate Hyper-V checkpoint creation (snapshots) using Batch scripts with PowerShell, including standard vs. production checkpoints, naming conventions, and pre-change safety workflows.

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:

Type Contents Use Case
Standard Disk state + memory state + device state Development, testing, labs
Production Disk 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

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.

Navigation