Use PowerShell to Determine the Chain of VHD’s for a Virtual Machine on Hyper-V
You want to determine what VHD's exist for the virtual machines (VM's) that are virtualized on your Windows 8 or Windows Server 2012 Hyper-V virtualization host.
This may sound simple, but what if you have a base image or template that has been configured and then multiple VM's have been created using differencing disks that reference that single base image? If that weren't difficult enough to keep track of, you may also have snapshots of those VM's which are also classified as differencing disks in HyperV.
How do you easily figure out what the chain is for all of the VHD's or VHDX files that are necessary for a virtual machine? I couldn't find a way to determine this easily so I decided to write a PowerShell function to figure this out.
I recently added a second hard drive (an SSD) to my laptop computer and I want to move some of the virtual hard drive files to this drive.
1#Requires -Version 3.0
2#Requires -Modules Hyper-V
3function Get-VHDChain {
4
5 [CmdletBinding()]
6 param(
7 [string]$ComputerName = $env:COMPUTERNAME,
8 [string[]]$Name = '*'
9 )
10
11 try {
12 $VMs = Get-VM -ComputerName $ComputerName -Name $Name -ErrorAction Stop
13 }
14 catch {
15 Write-Warning $_.Exception.Message
16 }
17
18 foreach ($vm in $VMs){
19 $VHDs = ($vm).harddrives.path
20
21 foreach ($vhd in $VHDs){
22 Clear-Variable VHDType -ErrorAction SilentlyContinue
23
24 try {
25 $VHDInfo = $vhd | Get-VHD -ComputerName $ComputerName -ErrorAction Stop
26 }
27 catch {
28 $VHDType = 'Error'
29 $VHDPath = $vhd
30 Write-Verbose $_.Exception.Message
31 }
32
33 $i = 1
34 $problem = $false
35
36 while (($VHDInfo.parentpath -or $i -eq 1) -and (-not($problem))){
37 If ($VHDType -ne 'Error' -and $i -gt 1){
38 try {
39 $VHDInfo = $VHDInfo.ParentPath | Get-VHD -ComputerName $ComputerName -ErrorAction Stop
40 }
41 catch {
42 $VHDType = 'Error'
43 $VHDPath = $VHDInfo.parentpath
44 Write-Verbose $_.Exception.Message
45 }
46 }
47
48 if ($VHDType -ne 'Error'){
49 $VHDType = $VHDInfo.VhdType
50 $VHDPath = $VHDInfo.path
51 }
52 else {
53 $problem = $true
54 }
55
56 [pscustomobject]@{
57 Name = $vm.name
58 VHDNumber = $i
59 VHDType = $VHDType
60 VHD = $VHDPath
61 }
62
63 $i++
64 }
65 }
66 }
67}
I've already moved a couple of the VHDX files as you can see in the results where the VHDType is "Error":
µ