Posey's Tips & Tricks
How To Use PowerShell to Mount a Hyper-V Virtual Hard Disk
Programmatically mount and access Hyper-V virtual hard disks, including assigning drive letters and manipulating variables, with these easy step-by-step instructions.
|• Learn the basic process of using PowerShell to mount Hyper-V virtual hard disks (VHDX files) and access their contents.|
• Important considerations include ensuring the VHDX file is not actively used, not encrypted, and does not contain any checkpoints.
One of my favorite things about Hyper-V has always been the portable nature of virtual hard disks (VHDX files). Assuming that a VHDX file is not encrypted, you can copy the file to another system and then mount the file as a drive and explore its contents.
Recently, I found myself in a situation where I needed to mount several virtual hard disks programmatically and use a script to write data to the virtual hard disks. Even though this does not seem like an overly difficult task, the devil is in the details. As such, I wanted to show you how my script works.
Before I get started, there are a couple of things that I need to tell you. First, this article assumes that the virtual hard disk file that you are interacting with is not being actively used by a virtual machine or by any other mechanism. I am assuming that no other processes are accessing the file.
Second, I am assuming that the virtual hard disk is not encrypted. This process will not work for an encrypted drive.
Third (and this is the big one) it is extremely important that the virtual hard disk does not contain any checkpoints. If you try using this technique on a virtual hard disk that has checkpoints associated with it, you will destroy the checkpoint chain.
So with that said, let's take a look at how to mount a virtual hard disk. The PowerShell cmdlet used to mount a virtual hard drive is Mount-VHD. At its simplest, you need to provide a path and filename for the virtual disk that you want to open. As you may recall though, the overall goal was to programmatically mount and then access the virtual disk. This means that you need a way of assigning a drive letter to the virtual hard disk. This is where things get to be a little bit tricky.
In my environment, I have a VHDX file named H.VHDX. I could mount this file by entering:
While this approach works, the command produces no visible output. More importantly, PowerShell does not capture the drive letter that is assigned to the virtual hard disk. This is a big problem if the goal is to interact with the virtual hard disk's contents.
The way that I solved this problem was to create two variables. The first one, which I will call $H, maps to the command used to mount the virtual hard disk. The second variable, which I will call $HLetter, will store the drive letter used when the disk was mounted. Here are the two commands that I used:
$H=Mount-VHD h.vhdx -passthru | Get-Disk | Get-Partition | Get-Volume
You can see what this looks like in Figure 1.
Now that you have a variable containing the drive letter, you may be able to use it as-is. In some cases however, PowerShell may have trouble accepting a variable in place of a literal drive letter. In such cases, you can use string manipulation to form the command from which you want to reference the drive letter. You can then use the Invoke-Expression cmdlet to run the string's contents as a command.
Suppose, for example, that you wanted to run the Get-ChildItem cmdlet against the drive referenced by the $HLetter variable. You could easily do this by typing: Get-ChildItem $HLetter. Suppose for a moment however, that you had to resort to string manipulation for this simple task. You might accomplish the task at hand by using commands such as:
$String='Get-ChildItem ' + $HLetter
$String | Invoke-Expression
You can see what this looks like in Figure 2.
The last task that you will need to perform as a part of this process is that of dismounting the virtual hard disk when you have finished using it. Thankfully, this is really easy to do. Just use the Dismount-VHD cmdlet, followed by the name of the VHDX file that you want to dismount. If for example, I wanted to dismount H.VHDX, I would type: Dismount-VHD H.VHDX
You can see what this looks like in Figure 3.
About the Author
Brien Posey is a 21-time Microsoft MVP with decades of IT experience. As a freelance writer, Posey has written thousands of articles and contributed to several dozen books on a wide variety of IT topics. Prior to going freelance, Posey was a CIO for a national chain of hospitals and health care facilities. He has also served as a network administrator for some of the country's largest insurance companies and for the Department of Defense at Fort Knox. In addition to his continued work in IT, Posey has spent the last several years actively training as a commercial scientist-astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space. You can follow his spaceflight training on his Web site.