Search Wiki:
Changes in release 1.7
- Added a new commandline parameter /server to provide ability to run this from a non-HyperV machine too even from a Windows Server 2003 or Windows XP system
- This change will facilitate finding stale VHDs in a network; refer to this link for more info http://www.ravichaganti.com/blog/?p=799

For complete documentation, feedback and questions, please visit http://www.ravichaganti.com/blog/?page_id=612


Background

With Virtual Server 2005, VHDMOUNT tool can be used to mount/unmount VHD files. But this requires a some tedious setup including setting up IIS. However, when Hyper-v was first released, there was no such tool like VHDMOUNT to mount and unmount VHDs. That is when I created a tool called VHDMOUNT.VBS http://www.ravichaganti.com/blog/?p=241 to enable VHD mount / dismount from command-line. VHDMOUNT.VBS along with a registry hack created ways to enable mount / unmount operations within the right-click context menu for a given VHD file. However, there are many others actions which can be performed on VHD files. Some of these include
  • Compact VHD
  • Convert VHD
  • Expand VHD
  • Inspect VHD
  • Merge VHD (new feature in 1.4 onwards)
  • Retrieve VHD details like,
    • Is VHD in use?
    • Type of a VHD
    • Is the VHD in saved state?
    • What are the Max Internal Size and File Size values in GB?
    • VM to which a given VHD is connected
This tool, Shell Extensions for VHD files, will enable all the above mentioned operations along with mount / unmount within the right-click context menu for a VHD file. With these shell extensions, it becomes easy to manage VHDs outside of Hyper-V MMC.

Requirements

This script works all of the following operating systems and requires Hyper-V WMI interfaces to function. Hence, Hyper-v role is not mandatory :) -- starting release 1.7. If you have any one Hyper-V Server in the network, you can use that for running the shell extensions even from a Windows Server 2003 or Windows XP system.

  • Windows Server 2008 with Hyper-V role or Windows Server 2008 Server Core with Hyper-V role
  • Hyper-V Server 2008
  • Windows Server 2008 R2 with Hyper-V role or Windows Server 2008 R2 Server Core with Hyper-V role
  • Hyper-V Server 2008 R2

Setting up VHD shell extensions

  • Download the VBScript file from the downloads tab
  • copy the script file to permanent location from where you want to run the script
  • Open command-prompt and change to the folder where you copied VHDShellExt.vbs
  • Run, cscript VHDShellExt.vbs /Action:Setup (This step will complete the registry changes required for VHD Shell Extensions)

Now, open Windows Explorer and locate a VHD file. On right-click, you must see a menu as shown here.
Menu.jpg

Default action for VHD file is Detail. Hence, double-click on a VHD file brings up details of the VHD file.

While this script has been written to make it earlier to manage VHD files using the Right-click context menu or Shell extensions, the same will work from command-line too. This has been designed like this to facilitate usage of this tool Server Core OS with Hyper-V role or Hyper-V server 2008

I have provided a progress window (starting release 1.6) to show progress of actions such as validate, expand, compact, convert, merge and mount. Without this progress information it was really tough to understand if there was some operation by the script. In case you are using context menu or WScript to run the script, you will see an IE progress window as shown here. If you are using this script on a Server Core machine or running the script using cscript.exe, you will see only a few dots on the screen representing the progress.

Progress.jpg

Error.jpg

Usage from command-line

cscript VHDShellExt.vbs /Server:<Hyper-V Server Name> /Action:[Expand|Convert|Compact|Mount|UnMount|Detail|Validate|Merge|Setup] /VHD:<Absolute_Path_to_VHD>

/Server:<Hyper-V Server Name>
Server will let you run the specified action on a non-HyperV system by using the Hyper-V Server instance for WMI interfaces. This is an optional parameter. If not specified, "." / localhost will be used as the server name.

/Action:Setup
Setup action will enable to VHD shell extensions on the system you are running this script. Script path is automatically captured and hence you need to copy the downloaded script to a permanent location and run it from there. If action is set to setup, providing /VHD parameter is meaningless and has no affect on the script execution.

If you use /server option along with /setup, what ever server name you sepcify will be used in the registry entries for creating all the context menu commands. If not, "." will be used as the value for /server in the registry. Use /Server to specify a different server name other than local machine to use a remote hyper-V Server WMI interfaces to run the VHDShellExt.vbs

/Action:Validate
Validate operation inspects a given VHD and reports if the file is valid or not.

/Action:Mount
Mount action mounts a VHD file so that the file can be accessed as disk. This action cannot be performed while the VM using the VHD is running.

/Action:UnMount
Unmount action dismounts the previously mounted VHD file.

/Action:Expand
Expand operation expands the selected VHD by given size. This action applies only to fixed and dynamic VHDs. The new size value specified during this action has to be at least 512MB more than the current VHD Max internal size. You should not expand a parent VHD with child VHDs or differencing disks. By doing so, you will invalidate the child VHD. You cannot perform this action while the VM is running.

/Action:Convert
Convert operation converts a fixed VHD to Dynamic and vice versa. This operation involves creating a new VHD file and you will be prompted to enter the absolute path to new VHD file. You should not convert a parent VHD with child VHDs or differencing disks. By doing so, you will invalidate the child VHD.You cannot perform this action while the VM is running.

/Action:Compact
Compact operation reduces the overall size of a dynamic disk or a differencing disk. This action is not applicable to fixed VHDs. You cannot perform this action while the VM is running. You should not compact a parent VHD with child VHDs or differencing disks. By doing so, you will invalidate the child VHD.

/Action:Merge
Merge action works only on differencing disks. This action merges the selected VHD in to it's immediate parent or a new VHD of your choice. Merge snapshots manually in to a VM's VHD might make VM non-functional.

/Action:Detail
Detail action retrieves the information about a VHD file. This information includes, size of the VHD, VHD in use?, VHD in saved state?, VM associated with the VHD, etc

Examples

cscript VHDShellExt.vbs /action:setup

cscript VHDShellExt.vbs /action:mount /vhd:c:\test1.vhd

cscript VHDShellExt.vbs /action:unmount /vhd:c:\test1.vhd

cscript VHDShellExt.vbs /action:detail /vhd:c:\test1.vhd

cscript VHDShellExt.vbs /action:expand /vhd:c:\test1.vhd

cscript VHDShellExt.vbs /action:convert /vhd:c:\test1.vhd

cscript VHDShellExt.vbs /action:compact /vhd:c:\test1.vhd

cscript VHDShellExt.vbs /action:validate /vhd:c:\test1.vhd

cscript VHDShellExt.vbs /action:type /vhd:c:\test1.vhd

cscript VHDShellExt.vbs /action:merge /vhd:c:\test1.vhd

Known Issues


*For some reason, on Windows Server 2008 R2 with Hyper-V role, GetVirtualDiskInfo method returns FALSE for both InUse and InSavedState properties even though the VHD is in use by a virtual machine. This is a bug that I just discovered. However, a mounted VHD not attached to a VM returns correct values.
Last edited Oct 11 2009 at 9:34 AM  by kanthrc, version 25
Comments
mikesmth wrote  Oct 22 2009 at 12:47 PM  
Nice Work!

I added some functions to bring the mounted volume online as well...
Just add a call to MountAll() in the Mount_VHD() function, just after succesfully mounting the VHD.

Function MountAll()
Dim oWMI
Dim colItems
Dim objItem
Dim sDeviceID
Dim Test
Dim HasPartitions
Dim colTest

HasPartitions=False

Set oWMI= GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strServer & "\root\cimv2")

Set colItems = oWMI.ExecQuery("SELECT * FROM Win32_DiskDrive")

For Each objItem In colItems
if (Left(objItem.Caption,4)="Msft") Then
MountDisk(objItem.Index)
end if
Next
End Function


Function MountDisk(sDiskID)
Dim oShell
Dim oScriptExec
Dim oStdOut
Dim oStdIn
Dim strElement
Dim sOut
Dim sLine

Set oShell = CreateObject("WScript.Shell")
Set oScriptExec = oShell.Exec("diskpart")
Set oStdOut = oScriptExec.StdOut
Set oStdIn = oScriptExec.StdIn
oStdIn.write vbCRLf
oStdIn.write "SELECT DISK " & sDiskID & vbCRLf
oStdIn.write "ONLINE DISK" & vbCRLf
oStdIn.write "EXIT" & vbCRLf
Do While Not oScriptExec.StdOut.AtEndOfStream
sLine=oScriptExec.StdOut.ReadLine
if instr(sLine,"successfully") then
sOut= sLine & vbCrLf
end if
Loop

If (strScriptEngine = "wscript") And IsObject(objIE) Then
Set strElement = objIE.Document.GetElementById("progress")
strElement.InnerText = strElement.InnerText & vbCrLf & sOut
Else
WScript.Echo sOut
End If
oStdIn.close()
End Function

kanthrc wrote  Nov 11 2009 at 10:29 AM  
Thanks. Pls feel free to share the code updates. I can post it here so that it will be helpful for others too.

Updating...
Page view tracker