Save to My DOJO
The Get-VHD PowerShell cmdlet grabs all VHD information associated with the specified VHD. It can be very useful if you want to either quickly gather information about all the VHDs on a host or just a single VHD. The information generated from Get-VHD can also be used in an automated weekly script to display information of selected VHDs.
Obtaining VHD Info from VHDs
One of the easiest ways to obtain VHD information of a VHD is to use the –Path parameter to specify the path of the VHD you want to gather information from:
Get-VHD –Path “C:ClusterSTorageVolume1VHDSTGLAB-BK01.
"
Now we get a display of the VHD information of the specified VHD file:
Obtaining VHD info from a VM
To obtain the VHD information of all VHDs attached to a specified VM, use the –VMId parameter. Since the Virtual Machine ID of each VM looks like this format “baaba8b4-a91e-40ff-8464-a40773755870”, it would be very tedious to memorize and keep track of this for every VM. Fortunately, if we use the Get-Help cmdlet, we can find an easier way to obtain the VHD information based on VM:
Get-Help Get-VHD –Full
We can see that the –VMId parameter accepts pipeline input:
This will allow us to use the ever so useful Get-VM cmdlet to specify the VM that we want. Then, we pipe that through Select-Object to get only the Virtual Machine Identifier property from the VM. Finally, we pipe it through again to Get-VHD’s parameter. In this example, we will get the VHD information on all VHDs that are attached to the TGLAB-DC01 VM:
Get-VM –VMName TGLAB-DC01 | Select-Object VMId | Get-VHD
We now get a display of the different properties of each VHD that is attached to the VM TGLAB-DC01:
Getting VHD info from Multiple VMs
To get VHD information from all VMs on a host, simply use the asterix (*) symbol after the –VMName parameter to specify all VMs:
Get-VM -VMName * | Select-Object VMid | Get-VHD
We now get a display of all VHDs associated with all VMs on the host:
To get VMs from multiple hosts, simply use the –ComputerName parameter with the Get-VM cmdlet. In this example we will specify the two hosts TGLAB-HV01 and TGLAB-HV02:
Get-VM –VMname * -Computername TGLAB-HV01,TGLAB-HV02 | Select-Object VMId | Get-VHD
Being able to generate this info for all our VHDs is very useful. However, the list can get lengthy and tedious to look through. Thanks to the magic of PowerShell, we convert this information into a format that is easier to read.
Converting Information to HTML
The benefits of converting information over to HTML format not only provides better readability, but also allows the information to be saved, stored, shared, and emailed. To this, we simply pipe our VHD information to the ConvertTo-HTML cmdlet and then use the redirection operator (>) to send the HTML code to a .htm file. In this example we will name the .htm file “vhdreport.htm” and place it in the C: directory:
Get-VM –VMName * | Select-Object VMid | Get-VHD | ConvertTo-HTML > “C:vhdreport.htm"
When vhdreport.htm is opened up in a web browser, we now get an HTML table that is much easier to read than the information displayed in the PowerShell console:
The HTML document still has a lot of information. If we wanted to take it a step further and have only certain properties be displayed, we can pipe our command to Get-Member, or GM for short, to see which properties are available to display:
Get-VM –VMname * | Select-Object VMid | Get-VHD | Get-Member
Let’s say we just want to see the path of our VHDs, the host that each VHD is on, the size of the VHD file, and the VHD type. To do this, we would simply use the –Property parameter with ConvertTo-HTML and list only the properties that we want to see:
Get-VM * | Select-Object VMId | Get-VHD | ConvertTo-HTML –Property path,computername,filesize,vhdtype > “C:SimpleVHDReport.htm"
Now, when we open up simpleVHDReport.htm, we see an HTML table with only the information we specified:
Let’s not stop there. The file size information can be a little difficult to interpret into GBs just by looking at it. Thanks to PowerShell we can convert this information into GBs on the fly while we are inputting our command!
We can use a hash table in place of the filesize property to perform the conversion at the same time we are listing the properties:
Get-VM –VMname * | Select-Object VMId | Get-VHD | ConvertTo-HTML –Property path,computername,vhdtype, @{label=’Size(GB)’;expression={$_.filesize/1gb –as [int]}} > “C:SimpleVHDReport.htm"
We now have the file size of our VHDs converted to GBs in the HTML table:
This could be extremely useful to run as a reoccurring script if you wanted to keep watch of the file size of each VHD, especially in an environment that heavily uses Dynamic disks.
Not a DOJO Member yet?
Join thousands of other IT pros and receive a weekly roundup email with the latest content & updates!
23 thoughts on "Getting VHD info using PowerShell with Get-VHD"
Thanks, Luke!
Very useful and detaled info.
Thanks, Luke!
Very useful and detaled info.
Hi Luke, great article! Do you maybe know if there’s a variation of this command that will allow you to see all the VM’s on a host including their VHD locations. The (Get-VM –VMName * | Select-Object VMId | Get-VHD) command lists all the vhd’s against the host but does not actually say which VM’s they are related to.
It’s a little ugly, but add-member doesn’t seem to return the original object so you kind of have to hack it together — I recommend saving it to a cmdlet or a function:
Get-VM | % { $vhd = Get-VHD -VmId $_.VmId; $vhd | Add-Member -NotePropertyName “Name” -NotePropertyValue $_.Name; $vhd; } | Format-Table
Fantastic page!
I’m new to Powershell, so this was exactly what I was looking for; an easy to read, step-by-step guide that teaches me section-by-section of the code what each part it aiming to achieve.
I’m now going to try to work on this code and expand it to pull the info for my entire cluster, not just one node.
Wish me luck 🙂
Thanks Luke!
Thanks for Great script and details.
hi,
from what I see this actually doesn’t work for VMs on multiple hosts (it only works for VMs from the host you are running on). the example in the articles also shows only VMs from one host (tglab-hv01). the error I get for VMs on another host is: “Get-VHD : Hyper-V was unable to find a virtual machine with the given criteria.”
Correct, to run it on multiple hosts you would need to use invoke-command or Get-VM -ComputerName Server1,Server2 | Select-Object VMId | Get-VHD
Thanks for the great detail!
I see you grabbed Get-VM to start, is there a way to keep the VM name (not just the hostname) in the output table? I’d like to link back all the VHDs to the VM they are connected to.
Thank you again!
Hi Paul,
The Microsoft.Vhd.PowerShell.VirtualHardDisk typename doesn’t contain a VM property, so we would need to create a more complex script using a psobject to display the VM. You can still link back each VHD to their VM by looking at the PATH field. By default the VHD’s are stored under the VM folder.
-Thanks!
thx u.
But this script only for offline VM?
Whan I tried run this script to all my VM, I see information only offline machine.
If VM Online: ” Error: ‘The process cannot access the file because it is being used by another process.’.
The operation cannot be performed while the object is in use.”
Hi Oleg, this should work with online VMs. Can you provide the command you are trying to run?