Posey's Tips & Tricks
How To Use PowerShell To Fix Hyper-V Virtual Disk Chains
Problem: Mounting a Hyper-V virtual hard disk outside of the VM breaks the VM. Solution: PowerShell.
One of the things I have always found handy about Hyper-V is the ability to mount a non-running virtual machine's (VM's) virtual hard disk in the host operating system.
This probably isn't something you would ever want to do in a production environment, but I can't even begin to tell you how many times I have done this in a lab environment. I just mount the virtual hard disk, copy a file, change a configuration setting or whatever, and then eject the virtual hard disk. Sure, you can do something similar using the Hyper-V Guest Services, but the Guest Services are somewhat limited.
The one issue with using the host operating system to mount a Hyper-V virtual hard disk is that if the VM has any checkpoints associated with it, then mounting the virtual hard disk outside of the VM will break the VM. The virtual disk will mount without any issues, but the next time you try to start the VM, you will receive an error message like the one that is shown in Figure 1.
The error occurs because mounting the VM outside of the VM breaks the relationship between the virtual hard disk and the checkpoint files. The data is all still there, but the parent-child relationship between the virtual disk file and the checkpoint file has been destroyed.
Additionally, if you modified the virtual disk's contents while it was mounted, then you may have potentially introduced some inconsistencies that will be difficult to resolve. Those types of inconsistencies, however, are beyond the scope of this article. For now, I want to focus on fixing the linkage between the virtual disks.
The first step in fixing the problem shown in Figure 1 above is to make note of the virtual disk's physical path and filename. You will need this information to fix the problem.
Now, open an elevated PowerShell window and navigate to the folder containing the virtual hard disk that you want to repair.
Windows includes a PowerShell cmdlet called Test-VHD. This command, which may be familiar to some of you, checks to see if a virtual disk chain is in a usable state. It returns a value of True if the chain is in act or False if the chain has been broken. If you look at Figure 2, you can see that when I run the Test-VHD cmdlet against the root virtual hard disk, I receive a value of True. When I run the cmdlet against the checkpoint, however, I receive an error message indicating that the chain is broken, followed by a value of False.
The PowerShell cmdlet used to fix this problem is Set-VHD. The Set-VHD cmdlet can redirect a child VHD to point at its parent after a virtual hard disk chain has been broken.
There are two parameters that I initially recommend using with this cmdlet. If the Set-VHD cmdlet fails to fix the problem, then there is a third parameter that you can use, but I recommend that you initially try to fix the problem without it because using the third parameter incorrectly can cause data loss.
The first parameter that you will have to use is -Path. This parameter is set to the name of the child virtual hard disk. In this case, the child is the checkpoint file.
The second parameter that you will need to use is -ParentPath. The -ParentPath parameter needs to be set to the name of the parent virtual hard disk. Here is what the command looks like:
Set-VHD -Path <child.vhdx> -ParentPath <parent.vhdx>
Now, remember when I said that sometimes you might have to use a third parameter. This is one of those situations. If you look at Figure 3, you can see that the Set-VHD cmdlet returned an error stating that the operation failed because of an ID mismatch. The fix for this problem is to use the third parameter.
The third parameter is -IgnoreIdMismatch (incidentally, the Microsoft documentation incorrectly lists this parameter as -IgnoreMismatchId). Remember, don't use this parameter unless you have to, because you can cause data loss if you use it incorrectly. In this case, though, I will use it. The command that I am using is:
Set-VHD -Path <child.vhdx> -ParentPath <parent.vhdx> -IgnoreIdMismatch
As you can see in Figure 4, the -IgnoreIdMismatch parameter fixes my problem and I am able to start the VM.
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.