# Windows 7 command script to mount VHD disk with assigned drive letter via DiskPart

I use VHD disk for storing my Dropbox files on my office PC.

I need the .vhd to be loaded automatically when booted i.e. I will just have to enter decode password instead of going all the way with Disk Manager tool e.g. guided here.

My google search came up with DiskPart command; though I cannot set drive letter without specifying volume id parameter. More google search came up with this thread, though using Powershell is not a native/favor way for me. I need a native Windows command that just works.

So my question is how to get volume id of a mounted VHD disk when calling DiskPart? Currently I have to set it as 3 which only applicable for my PC.

p.s.

1. Not looking for Powershell scripts
2. My DiskPart script can be viewed here 1) mount, 2) unmount
• Nam - I see a couple answer to this question and you've not accepted any. I wanted to share an answer of mine with you that runs pure CMD batch that may be helpful in your task with appropriate adjustments. While this "batch" script does use PowerShell functionality to get the information and allow the batch script to use it, you do NOT need to run it as a PowerShell script or from PowerShell command or IDE, you just run it from batch and use the more robust PS commands accordingly to get the needed information rather than a ton of batch logic for such a simple task. Apr 13, 2017 at 13:59
• Here's the post to my answer I mention above: superuser.com/questions/1165369/…. I encourage you to a least look at it just in case you find it helpful. Apr 13, 2017 at 13:59

I use a script which I found on the Internet a long time ago.

This script (MountVHD.cmd) generates a diskpart script and then calls diskpart with the generated script using the path and drive letter that you specify.

This script accepts two parameters:

MountVHD.cmd \path\to\vhdfile.vhd X


where X: is the drive letter to assign.

You can then create another command script which calls this with the command line above and place that calling script in the startup folder.

@echo off
setlocal enabledelayedexpansion

if {%1}=={} (
echo Usage: %~nx0 [vhd] [letter]
exit /b 1
)
set vhdPath=%~dpnx1
set driveLetter=%2

if {!driveLetter!}=={} (
echo Mounting !vhdPath!
) else (
echo Mounting !vhdPath! to !driveLetter!:
)

REM
REM create diskpart script
REM
set diskPartScript=%~nx0.diskpart
echo sel vdisk file="!vhdPath!">!diskPartScript!
echo attach vdisk>>!diskPartScript!

REM assign the drive letter if requested
if not {!driveLetter!}=={} (
echo select partition 1 >>!diskPartScript!
echo assign letter=!driveLetter!>>!diskPartScript!
)

REM Show script
echo.
echo Running diskpart script:
type !diskPartScript!

REM
REM diskpart
REM
diskpart /s !diskPartScript!
del /q !diskPartScript!

echo Done!

endlocal

• The select partition 1 diskpart command not works for me. Jan 8, 2016 at 4:54
• does it give an error? Jan 8, 2016 at 6:27
• Yes, kind of the volumn id not select Jan 8, 2016 at 9:04
• if you launch diskpart manually and do sel vdisk file = "path to vdisk file" and then do list partition .. what does it show? Jan 10, 2016 at 6:00
• Also, I've edited my answer above, I apologize. When specifying a drive letter to mountvhd.cmd, don't use the colon (:) Jan 10, 2016 at 6:03

Fact: It is not possible to write a single diskpart script which selects a specific drive letter for a mounted VHD !

But it is possible to make two diskpart calls (with two scripts) which are called by one batch or any other program.

Reason for the problem: There seems to be a timing issue, at least with some Windows versions as Windows 7. Diskpart is not waiting until the 'attach' is successful.

For some applications it seems no problem, because the drive letter once assigned will be remembered for the next time, so you can write scripts on ONE computer after first attach.

However, for a complete independent script this is not enough. Splitting it up in two diskpart commands is the only way to automate this, if you want to avoid powershell:

Here is a script as a solution (It avoids 'enabledelayedexpansion' for some reason, but this is not important, you can add this and remove goto commands, if you wish :-)

The script works even with no parameters. It has some nice features, e.g.

• It just looks for the .vhd name itself if not given :-)
• It creates the diskpart scripts in %TEMP% directory, because you are not guaranteed for having write access where the script is laying (and it is cleaner).

One thing to mention: Because the drive letter is changed during the second diskpart call, a "shadow entry" in Windows explorer for the old letter is possible to show up until opening explorer windows again.

@echo off

pushd "%~dp0"
set thisPath=%~dp0
setlocal

REM
REM Determining parameters
REM
REM You can specify the path to a specific vhd file in parameter 1, but you don't have to. Script will take 1st .vhd file found.
REM You can specify the driveletter - without colon - in parameter 2, but you don't have to. Script will take free drive letter found.
set vhdPath=%~dpnx1
set driveletter=%2
echo ThisPath: "%thisPath%"
if {%vhdPath%}=={} echo No specific VHD mentioned- will take first VHD file..

if not {%vhdPath%}=={} goto SpecificVHD
set SearchPath=%thisPath%*.vhd
echo SearchPath: %SearchPath%
for %%I in ("%SearchPath%") do (
rem echo File: "%%I"
set vhdpath=%%I
if exist "%%I" goto outloop
)
:outloop
:SpecificVHD
echo.
if not exist %vhdpath% (
echo Error! No .vhd file found in '%thisPath%' !
exit /B 1
)

echo VHD path: %vhdpath%
rem pause

if {%driveLetter%}=={} (
set Text=Mounting %vhdPath%
) else (
set Text=Mounting %vhdPath% to %driveLetter%:
)
echo %Text%
echo.

REM
REM Create diskpart script
REM
set diskPartScript=%TEMP%\%~n0.diskpart
echo Creating diskpart script: '%diskPartScript%'
rem exit /B 0
rem pause

echo sel vdisk file="%vhdPath%">"%diskPartScript%"
echo attach vdisk>>"%diskPartScript%"

REM
REM diskpart Part 1
REM
diskpart /s "%diskPartScript%"
del /q "%diskPartScript%"

REM Assign the drive letter if given
REM [it is assumed, that only 1 partition exists in the VHD]
if {%driveLetter%}=={} goto noSpecificDriveLetter
echo sel vdisk file="%vhdPath%">"%diskPartScript%"
echo select partition 1 >>"%diskPartScript%"
echo assign letter=%driveLetter%>>"%diskPartScript%"

REM timeout is not necessary on my system, but could be useful, so specified here
REM timeout /T 1 /nobreak

REM
REM diskpart Part 2
REM
diskpart /s "%diskPartScript%"
del /q "%diskPartScript%"

:noSpecificDriveLetter
echo Done.
popd
endlocal
pause


I have encountered a similar situation, and I hope maybe this will help you...

I backed up my old workstation's C drive to a VHD with a drive label of "Old_BG7". The VHDX file currently resides on a server here in my datacenter (\\bgserver\e$\Backup\NetOpsBG7_C$.vhdx). I desired to have this virtual disk mounted as my E: drive every time I logged in. The issue I ran into, however, was that Diskpart did not always assign the same Volume Number to my virtual disk.

Here is what I have done to work around that issue, and so far, it has been working for me.

I created a scheduled task which runs a batch script (C:\Users\BG\AppData\Roaming\BG_Stuff\NetOpsBG7_E$.cmd) at logon with elevated privileges. That batch script looks like this: @echo off diskpart /s "%userprofile%\AppData\Roaming\BG_Stuff\NetOpsBG7_C$.cfg"

for /f "tokens=2,3* delims= " %%i in ('echo list volume ^| diskpart ^| find /i "Old_BG7"') do if not %%j==E (echo select volume=%%i>"%userprofile%\AppData\Roaming\BG_Stuff\tmpScript.cfg" && echo assign letter=E>>"%userprofile%\AppData\Roaming\BG_Stuff\tmpScript.cfg" && echo exit>>"%userprofile%\AppData\Roaming\BG_Stuff\tmpScript.cfg" && diskpart /s "%userprofile%\AppData\Roaming\BG_Stuff\tmpScript.cfg" && del /q "%userprofile%\AppData\Roaming\BG_Stuff\tmpScript.cfg")

exit 0


The first command in the batch script calls this standard diskpart script (C:\Users\BG\AppData\Roaming\BG_Stuff\NetOpsBG7_C$.cfg): select vdisk file="\\bgserver\e$\Backup\NetOpsBG7_C\$.vhdx"
attach vdisk
exit


The real magic, however, happens in the second line of the batch script. I'm echoing the command 'list volume' into Diskpart, piping that output through the 'FIND' command to locate my VHD disk label "Old_BG7", then using 'FOR' to return two variables: the Volume Number and the Drive Letter of the mounted VHD. Then the 'IF' command takes over and checks to see whether the VHD's Drive Letter matches "E" or not. If it does, it just quits and exits; but if not, it writes, executes, and then deletes a temporary Diskpart script (C:\Users\BG\AppData\Roaming\BG_Stuff\tmpScript.cfg).

So, for example, if the VHD's assigned Drive Letter was not "E", and its Volume Number turned out to be 5, then the tmpScript would look like:

select volume=5
assign letter=E
exit


Hope this helps...

-=B

• This answers the OP's original question of "how to get volume id of a mounted VHD disk when calling DiskPart". The other answers assume the Volume ID is always 1 -- see where each script contains the line [...] select partition 1. I found, however, that Diskpart did not always assign the same Volume Number to my virtual disk. Therefore, regardless of the Volume Number assigned to my VHD, my script will find the correct volume and assign the preferred drive letter to it. Sep 17, 2017 at 2:23