Updated – 30/01/2024 – The tool was updated to include the VLAN Access ID that is set on the network adapter for each VM in the Hyper-V Cluster.
Updated – 29/09/2023 – The tool was updated to include the disk identifier for each VM/VHDX in the Hyper-V Cluster.
Updated – 06/03/2023 – The tool was updated to include memory, CPU, and network IP addresses for each VM in the Hyper-V Cluster.
In this article, we will share with you how to get the list of all VMs in the Hyper-V Cluster and their Virtual Hard Disks with PowerShell.
Table of Contents
Introduction
A while ago, we published a PowerShell script that will query System Center Virtual Machine Manager (SCVMM) to get all Virtual Machines including their Virtual Hard Disks, then it will calculate the size and percentage used for each VHD(X), and finally send you a nicely formatted HTML report. You can read all about it here.
In this blog post, we will share with you how to get the same report in comma-separated value (CSV) format and without SCVMM.
This comes in handy when working with a large Hyper-V cluster with many VMs, and you want to know the type of each virtual hard disk attached to every VM including their footprint size on the disk, and the remaining disk space so you know before the VM runs out of disk space.
Prerequisites
To run the function below successfully, you should note the following points:
1) You need to have Failover Cluster Module for Windows PowerShell installed on your machine:
Install-WindowsFeature -Name RSAT-Clustering-PowerShell
2) You need to have Hyper-V Module for Windows PowerShell installed on your machine:
Install-WindowsFeature -Name Hyper-V-PowerShell
3) Make sure to run (execute) the entire script first before you run it against your Cluster because this is a PowerShell function.
If you are working interactively in the console then the entire function can be copied and pasted into that session, then it will be available for the duration of that session.
I find this easier to do via the PowerShell ISE or Visual Studio Code than the standard PowerShell console.
So, you need to copy the function into the script pane, then click the Green Run Script or hit the F5 button. The function will be available for use and if using the ISE will appear interactively when you start typing the name as shown in the figure below:

Now, if the function below is something that you wish to use regularly in your interactive PowerShell sessions, then you can place it in your PowerShell Profile and it will be available every time you open your PowerShell console.
Learn more about PowerShell profiles and how to create one. Once you have created a PowerShell profile, place the function below in your profile and save it. Now every time you open your PowerShell console, the function will be available to use.
Another option is to store the function in a module. Using a PowerShell module is a more advanced significantly more structured and powerful method.
4) Last, you can run the function as follows:
Get-VMVHDs -ClusterName "HyperV-Cluster-Name" -Verbose
Get The List of All VMs in a Hyper-V Cluster
Here is the PowerShell function that will do the job for you:
Function Get-VMVHDs {
<#
.Synopsis
A script used to find all VHD(X) files for all VMs in a Hyper-V Cluster
.DESCRIPTION
A function used to find all VHD(X) files for all VMs in a Hyper-V Cluster,
including the type of each virtual hard disk attached to every VM with their footprint size on disk,
and the remaining disk space, so you know before the VM runs out of disk space.
Finally, it will export the report into a CSV file.
The report will also include the IP addresses, virtual memory and virtual CPU for each VM.
.Notes
Created : 03-12-2018
Updated : 19-02-2024
Version : 3.3
OS : Windows Server 2016, 2019, 2022, 2025 Hyper-V or later
Author : Charbel Nemnom
Twitter : @CharbelNemnom
Blog : https://charbelnemnom.com
Disclaimer: This script is provided "AS IS" with no warranties.
.EXAMPLE
. .\Get-VMVHDs.ps1
Get-VMVHDs -Cluster "Cluster-Name"
#>
[CmdletBinding(SupportsShouldProcess = $true)]
Param(
[string]$ClusterName
)
Get-ClusterGroup -Cluster $ClusterName | ? { $_.GroupType -eq 'VirtualMachine' } | Get-VM | ForEach-Object {
$vhd = Get-VHD -ComputerName $_.ComputerName -VmId $_.VmId
$networkAdapter = Get-VMNetworkAdapter -VM $_
$vhd | Add-Member -NotePropertyName "Name" -NotePropertyValue $_.Name
$vhd | Add-Member -NotePropertyName "ProcessorCount" -NotePropertyValue $_.ProcessorCount
$vhd | Add-Member -NotePropertyName "MemoryStartup" -NotePropertyValue $_.MemoryStartup
$vhd | Add-Member -NotePropertyName "NetworkAdapters" -NotePropertyValue $networkAdapter.IPAddresses
$vhd | Add-Member -NotePropertyName "AccessVlanId" -NotePropertyValue ($networkAdapter | Get-VMNetworkAdapterVlan).AccessVlanId
$vhd
} | Select-Object @{label = 'VM Name'; expression = { $_.Name } }, @{label = 'vCPU'; expression = { $_.ProcessorCount } }, `
@{label = 'vMem (GB)'; expression = { $_.MemoryStartup / 1gb –as [int] } }, `
@{label = 'IP Addresses'; expression = { $_.NetworkAdapters } }, @{label = 'Host Name'; expression = { $_.ComputerName } }, `
@{label = 'VLAN Id'; expression = { $_.AccessVlanId } }, Path, VhdFormat, VhdType, `
@{label = 'Size On Physical Disk (GB)'; expression = { $_.FileSize / 1gb –as [int] } }, `
@{label = 'Max Disk Size (GB)'; expression = { $_.Size / 1gb –as [int] } }, `
@{label = 'Remaining Space (GB)'; expression = { ($_.Size / 1gb - $_.FileSize / 1gb) –as [int] } }, `
@{label = 'Disk Identifier'; expression = { $_.DiskIdentifier } } `
| Export-Csv -Path "C:\$($ClusterName)-VMReport.csv" -NoTypeInformation -Force
Write-Verbose "The VM report is exported to C:\$($ClusterName)-VMReport.csv"
}
And here is the final report in CSV format:

The report will also include the VLAN Access ID that is set on the network adapter for each VM in the Hyper-V Cluster.
This is version 3.3, do you want additional features? Please feel free to leave a comment below.
Make sure to check my recent Windows Server Hyper-V Cookbook for in-depth details about Hyper-V!
Enjoy :)
__
Thank you for reading my blog.
If you have any questions or feedback, please leave a comment.
-Charbel Nemnom-
Hi , Can you add OS to the export as well?
Hello Michael,
I usually set the OS Name and the VM Name identical.
The script is returning the VM Name which is the computer name.
Please give it a try and let me know if it works for you.
Thanks!
Great work. Thank you!
I had to replace the quotation marks for the script to run.
Thank you Christian for the feedback, I have updated the quotation marks.
Hi
How should i get the VMVHDs.ps1 scripts?
Hello, you could copy the VMVHDs.ps1 script from the ‘Black Code’ box above.
It worked, please feel free to remove my earlier comments. Thanks a lot. This is amazing script and helped me a big time. :)
Would love to see the vMem and vCPU of each VM added to this report.
This script is not working.
Hello Toufiq, saying this script is not working without additional info is not helpful here.
I have tested this script and it has been reported by many users in the comment section that it’s working.
Please provided more info. Thanks!
Thanks for the reply, maybe I am doing wrong, when we run on the Hyper-V cluster it is not showing output.
Can you send the script where just we need to enter the Cluster name?
Hello Toufiq, thanks for providing more details.
First of all, this is a PowerShell function. So you need to run the entire script first, and then you run the following command within the same PowerShell session to get the report:
I have updated to script to include the vMem and vCPU for each VM added to this report as well.
Hope it helps!
Hello Jarek,
I am happy to inform you, that the script was updated to include the vMem and vCPU for each VM added to this report as well.
Enjoy it :)
Hi,
Thanks a lot, the script is working.
Can we add the IP address to the list?
Hello Wael, thanks for the comment and feedback!
Yes, sure we can do that.
The tool was updated to include memory, CPU, and network IP addresses for each VM in Hyper-V Cluster.
Enjoy it :)
Hi Charbel,
I am sure the script works as many mentioned here, however I am not finding the way to properly run it. I am testing it on Windows Server 2022 DataCenter.
Can you please update the blog with steps how to run the script end-to-end.
Thanks for your effort, between I ran the script with cluster disk and got the following errors:
Get-VHD : Failed to get the disk information.
Failed to open attachment ‘….vhds’. Error: ‘The
process cannot access the file because it is being used by another process.’.
Hello Agron, thanks for the comment and feedback!
Please note that I have updated the blog and added a new Prerequisites section with more details.
Let me know if it works for you now.
Hello PowerMan, thanks for the feedback!
The error that you noted above is related to the VHDX being locked in one of your VMs.
There are multiple reasons why the VHDX file is locked in your case.
It’s difficult to find the reason without looking at the cluster in more details.
First, I would look at the VM in question and then check if the VM has a DVD drive (ISO) attached to it (you can set it to None or Dettach it).
Hope it helps!
Hi Charbel,
Thank you. It is way more clear. You may also add (Get-VMVHDs -ClusterName “Cluster-Name”) in the procedure, now it’s only in the questions section.
Furthermore, the report generated is not showing the correct utilization which is seen within the VM. If I go and see the C Drive of one VM, as an example from 80GB is used 30GB, but the report shows used 79GB and the Remaining 1GB.
Any idea why this is happening and how to get the correct utilized disk space?