You dont have javascript enabled! Please enable it! Get The List Of All VMs In Hyper-V Cluster And Their Virtual Hard Disks - CHARBEL NEMNOM - MVP | MCT | CCSP | CISM - Cloud & CyberSecurity

Get The List of All VMs in Hyper-V Cluster and Their Virtual Hard Disks

4 Min. Read

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.

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:

Run PowerShell Function
Run PowerShell Function

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:

List of All VMs in Hyper-V Cluster and Their Virtual Hard Disks
List of All VMs in Hyper-V Cluster and Their Virtual Hard Disks

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-

Photo of author
About the Author
Charbel Nemnom
Charbel Nemnom is a Senior Cloud Architect with 21+ years of IT experience. As a Swiss Certified Information Security Manager (ISM), CCSP, CISM, Microsoft MVP, and MCT, he excels in optimizing mission-critical enterprise systems. His extensive practical knowledge spans complex system design, network architecture, business continuity, and cloud security, establishing him as an authoritative and trustworthy expert in the field. Charbel frequently writes about Cloud, Cybersecurity, and IT Certifications.
Previous

How To Be an MVP In Life Not Only In Technology #MVPBuzz #MVPInLife

How To Monitor Azure File Sync #AzureFiles #AzureMonitor #AFS

Next

39 thoughts on “Get The List of All VMs in Hyper-V Cluster and Their Virtual Hard Disks”

Leave a comment...

  1. Hello Agron, thanks for the feedback!
    Please note that the procedure on how to run this function is noted in the script itself under the EXAMPLE section.
    In regard to your question, I just ran the script in my environment and I can see the report shows the correct values.
    I have a VM with 100 GB Dynamic VHDX as Max Disk Size, the Size On Physical Disk is 8 GB, and the Remaining Space is 92 GB.
    Could you please confirm that the VM you mentioned above has Dynamic or Fixed VHDX?
    If you are using Fixed VHDX, then what you see is expected and correct. The script is reading the VHDX information size.
    When you create a Fixed VHDX, they allocate 100% of the indicated space on the underlying physical media.
    Hope it helps!

  2. Hi Charbel,

    We have Dynamic and Differencing VhdType.
    It seems that issue is happening on both types, but certainly not to all resources, only to some.
    Isn’t the Hyper-V being updated correctly for the use of disk space for its VMs?

  3. Hi Charbel,

    Looking at this it has most of the info I need, the rest is specific for us so no need to add to the script.
    But the problem is that I don’t get it to work. :(
    It runs without any errors at all but it doesn’t create the CSV file
    I’ve run the prerequisites first and I tried running it with the code as it is and as a .ps1 file
    Regards Christian

  4. Hello Christian, thanks for the comment and feedback!
    Could you please confirm that you run the script as administrator?
    Open the PowerShell console as admin.
    From where are you running the script, on the C:\ drive?
    Try to change the location and ensure that you have enough permissions for the CSV file to be created.
    Hope it helps!

  5. Hi Charbel,
    I’m running it as a domain admin and tried it both in elevated mode and later in normal mode.
    The folder I’m running it from is C:\PowerShell and I’m running it on one node of our Hyper-V Cluster.
    I also tried changing where the CSV is created from C:\ that’s in your script to C:\PowerShell just to be sure that it isn’t permission thing.

  6. Hello Christian, thanks for the update!
    To be honest, this is really strange.
    Maybe you have done that, could you please confirm that you ran (executed) the entire script first before you ran it against your Hyper-V Cluster?
    Could you please try again running the function, I have updated the tool to include the -Force parameter as follows:

    Export-Csv -Path "C:\$($ClusterName)-VHDReport.csv" -NoTypeInformation -Force

    I am not sure if that makes sense in your environment, but it’s worth to give it a try.
    Hope it helps!

  7. Hello Marti, thanks for the feedback!
    I am happy to hear that the script is working for you.
    Please note that the tool was updated to return the ‘Disk Identifier’ attribute for all Virtual Hard Disks.
    Give it another try and let know if it works for you.

  8. I’m trying to execute this script, but it returns the following error:

    “The term ‘Get-VMVHDs’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.”

    I already have installed the Hyper-V modules

  9. Hello Lucas, as noted in the Prerequisites section.
    First, you need to 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.
    Check the Prerequisites section again.
    Hope it helps!

  10. Hello Martin, thanks for the feedback!
    Yes, it’s possible to add the VLAN ID that is set on network adapter for each VM.
    I have updated the tool, get a new copy and give it a try.
    It should work as expected.

  11. Hello Charbel,
    I could not understand what this (Remaining Space) represents.

    I have checked the guest and Total size is 200 GB, free space is 36.5GB, but I am getting this:
    FileSize : 214955982848
    Size : 215822106624
    if I am not wrong FileSize is actual disk size that we have assigned to the VHD and size is always 1 GB extra that I have seen while increasing the disk size.
    Is there any way in Hyper-V to get free/used size at guest level?

  12. Hello Arun, thanks for the comment and the follow-up question!
    The Remaining Space (GB) column represents the Remaining disk Size capacity at the guest level inside the OS.
    No, the “FileSize” is the current used space by the VM, and the “Size” is the actual disk size that you have assigned to the VHD, so if you subtract (Size-FileSize), you will get the Remaining Disk Space for the VM. In your case, the actual Size is (215822106624 Byte)=215GB and the FileSize is (214955982848 Byte)=215GB, are you using Fixed Disk, right?
    Please note that if your VM is using a Fixed Disk and not Dynamic, then the Remaining Space (GB) will be always Zero which makes sense. This tool applies to VMs with Dynamic Disks only.
    Hope it helps!

  13. Dear Charbel,

    I’ve tried your script and I’m running into some problems…
    First there seems a ANSI/UTF8 mismatch when you copy the code from your site.
    Second, when I do execute your script, there’s no output zero.

    When I try “Get-ClusterGroup -Cluster MyClusterName” I’ve some output and my Clustername is working.

    Help :)
    -Laurent

  14. Hello Laurent, thanks for the comment and feedback!
    I just validated the script from my side and it’s working fine.
    I’ve copied the code from the site to verify the ANSI/UTF8 mismatch that you mentioned. All is ok.
    As for the output, you need to run the entire function first (F5), and then enter the command as follows:
    Get-VMVHDs -ClusterName "ClusterName" -Verbose
    As I noted in the prerequisites section, make sure to run (execute) the entire script first before you run it against your Cluster because this is a PowerShell function.
    Let me know if it works for you.

Let us know what you think, or ask a question...