Save to My DOJO
Table of contents
It is probably a safe bet that the VHD and VHDX files in a Hyper-V environment are incredibly important. If the file isn’t where you expect it to be or if there is a problem with it, Hyper-V won’t be very happy. Typically when a virtual machine is running if there is a problem with a disk file you’ll know right away. But perhaps you have a library of virtual machines that aren’t always online. It would be better to know ahead of time if there is a problem by testing your VHD and VHDX files.
Here are some techniques using the PowerShell cmdlets in the Hyper-V 3.0 module.
Getting VHD Paths
Finding the associated file paths with virtual machine is pretty simple. The virtual machine has a hard drives property which is a collection of hard drive objects.
PS C:> get-vm chi-win8 | select -expand harddrives
Or, you can use the Get-VMHardDiskDrive cmdlet.
PS C:> Get-VMHardDiskDrive chi-win8
This works even better when used in a pipelined expression.
PS C:> get-vm chi* | Get-VMHardDiskDrive
I could have gotten all virtual machines. You can see the path, but that is only the configuration. There is no way of knowing if the file even exists unless you start the virtual machine or test.
Testing Path
One test we can do is to use the Test-Path cmdlet. This is an easy way to verify a file or folder exists.
PS C:> test-path c:windows True
To use with the Hyper-V cmdlets takes a little more because we need to get the Path property.
PS C:> Get-VMHardDiskDrive chi-fp01 | foreach { Test-path $_.path} True True True
Or here’s a neat trick we can do in PowerShell 3.0.
PS C:> Test-Path (Get-VMHardDiskDrive chi-fp01).Path True True True
The downside here is that if a file couldn’t be found PowerShell would return False, but I wouldn’t know which file failed. One solution is to simply add the test as a custom property.
PS C:> Get-VMHardDiskDrive chi-win8 | Select VMName,Controller*,DiskNumber,Path,@{Name="TestPath";Expression={$_ | Test-Path}}
This should work as well on multiple virtual machines and those with multiple drives.
PS C:> Get-VMHardDiskDrive chi-fp01,chi-dc01 | Select VMName,Controller*,DiskNumber,Path,@{Name="TestPath";Expression={$_ | Test-Path}}
Let’s check all of my virtual machines and see if there are any problems:
PS C:> Get-VMHardDiskDrive * | Select VMName,Controller*,DiskNumber,Path, @{Name="TestPath";Expression={$_ | Test-Path}} | where {-Not $_.TestPath}
Because of PowerShell’s object-based nature, this is a one-line command and now I can see where I have a problem.
Testing the VHD
But verifying the path is only half the battle. The file might exist but it might be corrupted or in the case of a differencing disk there may be an issue with the chain of disks. We can accomplish this with Test-VHD from the Hyper-V PowerShell module. It is as simple to use as this.
PS C:> Get-VMHardDiskDrive chi-win8 | test-vhd True PS C:> Get-VMHardDiskDrive chi-fp01 | test-vhd True True True
If there is a failure PowerShell will tell you and display the error.
Like Test-Path it is hard to tell what file goes with the result unless there is a problem. So we can expand our earlier pipelined expression.
PS C:> Get-VMHardDiskDrive "SystemCenter Demo",chi-win8,"demo rig" | Select VMName,Controller*,DiskNumber,Path, @{Name="TestPath";Expression={$_ | Test-Path}},@{Name="TestVHD";Expression={$_ | Test-VHD }}
Or I can filter for test failures as I did before. If this is something I wanted to use often, I’d turn it into a PowerShell function.
#requires -version 3.0 Function Test-VHDIntegrity { <# .Synopsis Test VHD files for integrity .Description Test the drive files for a Hyper-V virtual machine and verify the specified file exists and that there are no problems with it. .Example PS C:> Get-VM | Test-VHDIntegrity | Out-Gridview .Example PS C:> Get-VM | Test-VHDIntegrity | where {(-NOT $_.TestPath) -OR (-NOT $_.TestVHD)} .Link Test-Path Test-VHD #> [CmdletBinding()] Param ( [Parameter(Position=0,Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)] [alias("vmname","name")] [ValidateNotNullorEmpty()] [object[]]$VM ) Process { #write-verbose ($vm | out-string) foreach ($item in $VM) { Write-Verbose "Analyzing disks for $item" <# I intentionally omitted parameter names for Get-VMHardDiskDrive so that it can detect if it is processing a string or a virtual machine #> Get-VMHardDiskDrive $item | Select VMName,Controller*,DiskNumber,Path, @{Name="TestPath";Expression={$_ | Test-Path}}, @{Name="TestVHD";Expression={$_ | Test-VHD }} } #foreach } } #end function
With this function loaded into my PowerShell session I can now run commands like this to identify problems:
PS C:> get-vm | Test-VHDIntegrity | where {(! $_.TestPath) -or (! $_.TestVHD)}
I retrieved all the virtual machines, and tested the drives with my function for each one, then I filtered out all the results except those where one of the tests failed. Now I can see which virtual machines I need to look at in more detail. As with all the PowerShell samples I post here, please review and test thoroughly in a non-production environment.
Summary
The health and integrity of your VHD and VHDX files are paramount in Hyper-V. With a little PowerShell it is easy to discover problems before they become major headaches. Of course, this is another scenario where having decent backups is critical so that if a file is found missing you can easily restore it.
Not a DOJO Member yet?
Join thousands of other IT pros and receive a weekly roundup email with the latest content & updates!
15 thoughts on "Testing and Validating Hyper-V VHD/VHDX Files"
What is your go to steps to try to fix a corrupted VHDX from a power failure??
I suppose I would run CHKDSK on the drive first. If the VM can run I would probably run CHKDSK inside the VM as well. Otherwise, I guess I would hope I had a good backup or snapshot.
A day late and a dollar short in typical Microsoft fashion…