Skip to main content

How to Mount and Unmount a VHD File in Batch Script

Virtual Hard Disks (VHD/VHDX) are portable disk images used for backup snapshots, operating system deployment, and virtual machine storage. In many enterprise workflows, you need to mount a VHD temporarily to extract files, apply updates, or inject drivers, all without booting into it. Rather than opening Disk Management and clicking through the GUI, a Batch script can use the built-in DiskPart utility to attach and detach VHD files programmatically. This allows for fully automated pipelines where a disk image can be opened, modified, and sealed in seconds.

This guide will explain how to mount and unmount VHD files using Batch and DiskPart.

How DiskPart Scripting Works

DiskPart is an interactive command-line tool that accepts commands either interactively or via a script file. For Batch automation, you write DiskPart commands to a temporary text file and execute them with diskpart /s scriptfile.txt. DiskPart requires administrator privileges for all operations.

Method 1: Mount (Attach) a VHD with Drive Letter Assignment

This method mounts a VHD file and assigns a specific drive letter so the script knows exactly where the content is accessible.

Implementation

@echo off
setlocal

set "VHDPath=%~1"
set "DriveLetter=V"

if "%VHDPath%"=="" (
echo Usage: %~nx0 ^<path_to_vhd^> [drive_letter]
echo.
echo Examples:
echo %~nx0 C:\Images\Backup.vhdx
echo %~nx0 D:\VMs\server.vhdx Z
endlocal
exit /b 1
)

if not "%~2"=="" set "DriveLetter=%~2"

:: Verify admin privileges
net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] DiskPart requires administrator privileges. >&2
echo Right-click and select "Run as administrator." >&2
endlocal
exit /b 1
)

:: Verify the VHD file exists
if not exist "%VHDPath%" (
echo [ERROR] VHD file not found: %VHDPath% >&2
endlocal
exit /b 1
)

:: Check if the drive letter is already in use
if exist %DriveLetter%:\ (
echo [ERROR] Drive letter %DriveLetter%: is already in use. >&2
echo Choose a different letter or unmount the existing drive first.
endlocal
exit /b 1
)

echo [INFO] Mounting VHD: %VHDPath%
echo [INFO] Assigning drive letter: %DriveLetter%:

:: Create the DiskPart script
set "DPScript=%TEMP%\dp_mount_%RANDOM%.txt"
(
echo select vdisk file="%VHDPath%"
echo attach vdisk
echo wait
echo select partition 1
echo assign letter=%DriveLetter%
) > "%DPScript%"

:: Execute DiskPart
diskpart /s "%DPScript%" >nul 2>&1
set "DPResult=%errorlevel%"

:: Clean up the script file
del "%DPScript%" 2>nul

if %DPResult% neq 0 (
echo [ERROR] DiskPart failed to mount the VHD. >&2
echo Common causes: >&2
echo - VHD is already mounted or in use by Hyper-V >&2
echo - VHD file is corrupt or inaccessible >&2
echo - Insufficient disk space for dynamic VHDs >&2
endlocal
exit /b 1
)

:: Verify the drive is accessible
timeout /t 2 >nul
if exist %DriveLetter%:\ (
echo [OK] VHD mounted successfully at %DriveLetter%:\
dir %DriveLetter%:\ /a /o 2>nul | findstr /i "File(s) Dir(s)" 2>nul
) else (
echo [WARNING] DiskPart reported success but %DriveLetter%:\ is not accessible. >&2
echo The VHD may have multiple partitions or an unrecognized filesystem. >&2
)

endlocal
exit /b 0

Why select partition 1 and assign letter:

DiskPart's attach vdisk makes the disk visible to Windows, but does not automatically assign a drive letter. Without assign letter, the mounted VHD appears only in Disk Management with no drive letter, making it inaccessible to scripts. Selecting partition 1 and assigning a letter ensures a predictable mount point.

Why wait after attach vdisk:

The wait command tells DiskPart to complete the attach operation before proceeding. Without it, the select partition command may fail because the disk hasn't been fully recognized yet.

Method 2: Unmount (Detach) a VHD

This method safely ejects the virtual disk, flushing all pending writes before releasing the file.

@echo off
setlocal

set "VHDPath=%~1"

if "%VHDPath%"=="" (
echo Usage: %~nx0 ^<path_to_vhd^>
echo.
echo Example: %~nx0 C:\Images\Backup.vhdx
endlocal
exit /b 1
)

net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Administrator privileges required. >&2
endlocal
exit /b 1
)

echo [INFO] Unmounting VHD: %VHDPath%

set "DPScript=%TEMP%\dp_unmount_%RANDOM%.txt"
(
echo select vdisk file="%VHDPath%"
echo detach vdisk
) > "%DPScript%"

diskpart /s "%DPScript%" >nul 2>&1
set "DPResult=%errorlevel%"

del "%DPScript%" 2>nul

if %DPResult% neq 0 (
echo [ERROR] Failed to unmount VHD. >&2
echo The disk may not be currently mounted, or files may be in use. >&2
endlocal
exit /b 1
)

echo [OK] VHD detached successfully.
echo [INFO] The file "%VHDPath%" is now safe to move, copy, or delete.

endlocal
exit /b 0

Important: always unmount before modifying the VHD file

If you move, rename, or delete a .vhdx file while it is attached, you risk corrupting the filesystem inside the image. Always detach first.

Method 3: Read-Only Mount for Safe Inspection

Use this when you need to browse the contents of a VHD without risking accidental writes, for example, during forensic investigation, backup verification, or examining a VHD from an unknown source.

@echo off
setlocal

set "VHDPath=%~1"
set "DriveLetter=R"

if "%VHDPath%"=="" (
echo Usage: %~nx0 ^<path_to_vhd^> [drive_letter]
echo.
echo Mounts the VHD as read-only. No writes are possible.
endlocal
exit /b 1
)

if not "%~2"=="" set "DriveLetter=%~2"

net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Administrator privileges required. >&2
endlocal
exit /b 1
)

if not exist "%VHDPath%" (
echo [ERROR] VHD file not found: %VHDPath% >&2
endlocal
exit /b 1
)

if exist %DriveLetter%:\ (
echo [ERROR] Drive letter %DriveLetter%: is already in use. >&2
endlocal
exit /b 1
)

echo [INFO] Mounting VHD in READ-ONLY mode: %VHDPath%

set "DPScript=%TEMP%\dp_ro_mount_%RANDOM%.txt"
(
echo select vdisk file="%VHDPath%"
echo attach vdisk readonly
echo wait
echo select partition 1
echo assign letter=%DriveLetter%
) > "%DPScript%"

diskpart /s "%DPScript%" >nul 2>&1
set "DPResult=%errorlevel%"

del "%DPScript%" 2>nul

if %DPResult% neq 0 (
echo [ERROR] Failed to mount VHD in read-only mode. >&2
endlocal
exit /b 1
)

timeout /t 2 >nul
if exist %DriveLetter%:\ (
echo [OK] VHD mounted as READ-ONLY at %DriveLetter%:\
echo [INFO] No writes can be made to this disk.
) else (
echo [WARNING] Mount reported success but drive is not accessible. >&2
)

endlocal
exit /b 0

When to use read-only:

  • Forensic investigation: Ensures evidence integrity, the disk image cannot be modified.
  • Backup verification: Confirms backup contents are intact without risking changes.
  • Untrusted VHDs: Examining a VHD from an unknown source without risk of malware writing to your system.
  • Compliance: Some audit procedures require read-only access to demonstrate that data was not altered during review.

Method 4: Mount, Process, and Unmount Workflow

In automated pipelines (backup extraction, driver injection, file deployment), you often need to mount a VHD, perform operations, and unmount, all in one script with proper error handling.

@echo off
setlocal

set "VHDPath=%~1"
set "DriveLetter=V"
set "LogFile=%~dp0vhd_operations.log"

if "%VHDPath%"=="" (
echo Usage: %~nx0 ^<path_to_vhd^>
endlocal
exit /b 1
)

net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Administrator privileges required. >&2
endlocal
exit /b 1
)

if not exist "%VHDPath%" (
echo [ERROR] VHD file not found: %VHDPath% >&2
endlocal
exit /b 1
)

:: =============================================
:: Step 1: Mount the VHD
:: =============================================
echo [1/3] Mounting VHD...

set "DPScript=%TEMP%\dp_workflow_%RANDOM%.txt"
(
echo select vdisk file="%VHDPath%"
echo attach vdisk
echo wait
echo select partition 1
echo assign letter=%DriveLetter%
) > "%DPScript%"

diskpart /s "%DPScript%" >nul 2>&1
del "%DPScript%" 2>nul

timeout /t 2 >nul
if not exist %DriveLetter%:\ (
echo [ERROR] Failed to mount VHD. >&2
endlocal
exit /b 1
)

echo [OK] VHD mounted at %DriveLetter%:\

:: =============================================
:: Step 2: Perform operations on the mounted VHD
:: =============================================
echo [2/3] Processing files on VHD...

:: Example operations (customize these):
:: - Extract backup files
:: robocopy %DriveLetter%:\Backups C:\Restore /E /R:1 /W:1

:: - Inject a driver
:: copy C:\Drivers\network.inf %DriveLetter%:\Windows\INF\

:: - Verify a file exists
if exist %DriveLetter%:\Windows\System32\config\SYSTEM (
echo [OK] Windows system hive found on VHD.
) else (
echo [INFO] This does not appear to be a Windows system VHD.
)

:: Log the operation
echo [%date% %time%] Mounted and processed: %VHDPath% >> "%LogFile%"

:: =============================================
:: Step 3: Unmount the VHD (always runs)
:: =============================================
echo [3/3] Unmounting VHD...

set "DPScript=%TEMP%\dp_detach_%RANDOM%.txt"
(
echo select vdisk file="%VHDPath%"
echo detach vdisk
) > "%DPScript%"

diskpart /s "%DPScript%" >nul 2>&1
del "%DPScript%" 2>nul

echo [OK] VHD unmounted.
echo [%date% %time%] Unmounted: %VHDPath% >> "%LogFile%"

endlocal
exit /b 0

Why the unmount step always runs:

If the processing step fails or the script is interrupted, leaving the VHD mounted can cause problems, the VHD file is locked, Hyper-V cannot use it, and the drive letter is occupied. The unmount step should always execute. In this linear script, it runs unconditionally. For more complex workflows, consider adding error handling that jumps to the unmount step on failure.

How to Avoid Common Errors

Problem: "The Virtual Disk Is Already Attached"

If you try to mount a VHD that is already attached (or in use by Hyper-V), DiskPart fails with "The virtual disk service provider does not recognize this virtual disk."

Solution: Detach the VHD first using Method 2, or check if it is already mounted before attempting to attach:

:: Check if the VHD path appears in the mounted disks
powershell -NoProfile -Command ^
"if (Get-Disk | Where-Object Location -eq '%VHDPath%') { exit 0 } else { exit 1 }"
if not errorlevel 1 (
echo [INFO] VHD is already mounted.
)

Problem: No Drive Letter After Mounting

DiskPart's attach vdisk makes the disk visible but does not assign a drive letter. Without select partition 1 and assign letter=X, the VHD appears in Disk Management but is not accessible from scripts.

Solution: Always include select partition 1 and assign letter=X in your DiskPart script (as shown in all mount methods). If the VHD has multiple partitions, you may need to select a different partition number.

Problem: DiskPart Script File Left Behind

If the script crashes between creating the DiskPart script file and deleting it, the temp file persists. While harmless, accumulated temp files are messy.

Solution: Use %RANDOM% in the temp filename (as shown in all methods) to avoid collisions, and always del the script file immediately after DiskPart returns, even on error paths.

Problem: VHD File Permissions

If the VHD file is on a network share or in a directory with restricted permissions, DiskPart may fail even with admin rights because the SYSTEM account (which DiskPart uses internally) may not have access to the file.

Solution: Copy the VHD to a local directory before mounting, or ensure the share permissions grant access to the computer account.

Wrong Way: Double-Clicking the VHD to Mount

While Windows can auto-mount VHDs on double-click, this provides no control over read-only status, drive letter assignment, or automation compatibility. The VHD is mounted with whatever Windows chooses.

Correct Way: Use DiskPart for scripted, repeatable control.

Best Practices and Rules

1. Always Verify the Mount

After DiskPart reports success, verify the drive letter is actually accessible with if exist %DriveLetter%:\. DiskPart may report success even if the partition selection or letter assignment failed.

2. Always Unmount When Finished

A mounted VHD locks the .vhdx file. Hyper-V cannot start a VM using a VHD that is mounted by DiskPart. Always detach when your operations are complete.

3. Use Read-Only for Inspection

If you only need to read files from the VHD (backup verification, forensics, audit), mount as read-only (Method 3). This prevents accidental writes and preserves evidence integrity.

4. Log Mount and Unmount Operations

For compliance and auditing, record every mount/unmount operation with timestamps:

echo [%date% %time%] MOUNT: %VHDPath% on %DriveLetter%: >> "%~dp0vhd_activity.log"

5. Choose Unused Drive Letters

Before mounting, verify the chosen drive letter is not in use. Letters near the end of the alphabet (V, W, X) are safer choices because they are rarely used by physical drives or network mappings.

6. Handle Multi-Partition VHDs

Some VHDs (especially system images) contain multiple partitions (recovery, EFI, Windows). select partition 1 may select the recovery partition rather than the data partition. Use list partition in an interactive DiskPart session first to identify the correct partition number.

Conclusions

Mounting and unmounting VHD files via Batch script provides precise, repeatable control over virtual storage operations. By automating DiskPart commands with proper drive letter assignment, read-only options, error handling, and mount verification, you gain the consistency and speed needed for enterprise backup pipelines, OS deployment workflows, and forensic investigations. This automation eliminates the manual steps and human error inherent in GUI-based disk management.