Retrieve details of vms on each and every host server on the network

Hi,

I would like to use the invoke command to get the details of all vms installed on each and every server host on the network in a list format.

I have had a look on the internet but could not find anything that suits my needs.

The best I got so far is the following:

#Type Hyper-V host server names in $hosts variable
$hosts = “SRV1”, “SRV2, SRV3”
Get-VM -ComputerName $hosts | select-object -ExpandProperty NetworkAdapters

This works a bit , but no where where I would like it to be.

I need the output to look as such:

Server Name/host, Host IP, Host MAC, VM Name/Guest, Guest OS Name, VM IPv4, VM IPv6, VM MAC, VM Note

Thank you for your kind help.

Regards,

Boulbul

boulbul,
Welcome to the forum. :wave:t4:

Before we proceed … When you post code, sample data, console output or error messages please format it as code using the preformatted text button ( </> ). Simply place your cursor on an empty line, click the button and paste your code.

Thanks in advance

How to format code in PowerShell.org <---- Click :point_up_2:t4: :wink:

Really? Since it is pretty unlikely that you will find something exactly fitting your needs you should try to find something what’s close enough to your needs to be adapted easily. :wink:

When you search for “Retrieve details of vms on each and every host server” I am pretty sure you will find something useful or inspiring. :wink:

Regardless of that - I would recommend not to mix information about the host and the VMs in one table as some of the information would be redundand for the hosts and actually useless for the VMs. :wink:

What does it output? :wink: How do you think you could change the command to output more than just what it does now? :wink: :wink:

Hi Olaf,

Very happy to be accepted to the forum…and hope to remain here for a long time :grinning:

By taking your advice, I got to the following point.

get-vm | Select-Object ComputerName,Name,Id,Notes,State,NetworkAdapters|Format-Table

This is the output:

ComputerName Name Id Notes State NetworkAdapters
---- --
New-vm c1 8b89c96-d5a5-4c61-b63c-232d2133f192 Running {Network Card}
Boulbul test1 81de770f-54cb-4d1a-beed-097e0cc1155a Running {Network Card}
Boulbul test2 83551f8f-59e3-4681-bf5d-0f76c940a333 Off {Network Card}

As you can see, it does not show the network card details, but just the text "Network Card instead.

What I would like to add, is add to the result above IPv4, IPv6, Interface Name & MAC of the VM to this output.

This command launched from within the vm:

(get-vm).NetworkAdapters

Will yield:

Name         IsManagementOs VMName                    SwitchName MacAddress   Status IPAddresses                            
----         -------------- ------                    ---------- ----------   ------ -----------                            
Carte réseau False          Nouvel ordinateur virtuel            00155D6A2A06 {Ok}   {}                                     
Carte réseau False          test1                     Prive      00155D6A2A03 {Ok}   {169.254.12.49, fe80::d13c:2319:ac06...
Carte réseau False          test2                     Prive      00155D6A2A04        {}                                     

But, I need to associate this output with the one above (invoke command) in order to the get the this intended result:

ComputerName Name Id Notes State   IPAddresses        MacAddress
---- --
Boulbul test1 81de770f-54cb-4d1a-beed-097e0cc1155a Running 169.254.12.49  fe80::d13c:2319:ac06

Thank you for helping advance on my project.

Kind regards,

Boulbul

It does not just show the text “Network Card” it shows this in curly braces - that’s the actual interesting point on this output. Curly braces indicate that the property shown is an array. Even if there’s just one element in it what seems to be the case in your case.

The most common ways to combine the properties of the elements of those subarrays with the properies of the outer elements are ether calculated properties or nested loops combined with a “[PSCustomObject]”. Since I like the syntax of a [PSCustomObject] more I’ll show this:

Get-VM | 
ForEach-Object {
    $VM = $_  # this variable assignment makes the current pipeline object available inside the nested loop
    $NicList = $_.NetworkAdapters
    foreach ($Nic in $NicList) {
        [PSCustomObject]@{
            ComputerName    = $VM.ComputerName
            VM_Name         = $VM.Name
            VM_State        = $VM.State
            Nic_Name        = $Nic.Name
            Nic_MacAddress  = $Nic.MacAddress
            Nic_IPAddresses = $Nic.IPAddresses
        }
    }
}

Olaf,

Thank you very much for your kind help. The script is great…It does most of what I want…

I have developped it further to suit my needs, but I still have few issues though.


#forum

Get-VM | 
ForEach-Object {
    $VM = $_  # this variable assignment makes the current pipeline object available inside the nested loop
    $NicList = $_.NetworkAdapters
    foreach ($Nic in $NicList) {
        [PSCustomObject]@{
            ComputerName      = $VM.ComputerName
            Nic_IPAddresses   = $Nic.IPAddresses
            VM_Name           = $VM.Name
            Nic_MacAddress    = $Nic.MacAddress
            VM_CreationTime   = $VM.CreationTime
            VM_MemoryAssigned = $VM.MemoryAssigned
            VM_ID             = $VM.VMId
            VM_HD_Location    = $VM.VMId |Get-VHD| select ParentPath
            VM_HD_Size        = $VM.VMId |Get-VHD| select Size |select DeviceID, {$_.Size /1GB}
            VM_State          = $VM.State
            Nic_Name          = $Nic.Name
            
        }
    }
} |Format-Table  |Out-File C:\Temp\Hyper-V_VM_Details.cs

The issues that I am currently facing are:

  1. List item

I need the Guest and Host Operating System. I could not find any way with Get-VM
I found a script which does this…

#Script get Operating System.
        #show all properties for reference only
        (Get-WMIObject win32_operatingsystem) | select *
        #retrieve OS
        $OS1 = (Get-WMIObject win32_operatingsystem).caption
        #write it out
        write-host $OS1

However, combining the 2 together was a night mare.

  1. List item
    The Format-table does not display all output on the screen. I have even tried to redirect the ouput onto an excel file, but I got the same result.
    Is there anyway to keep the table format and get all the output on the csv/excel file?

This is the result

Many thanks for your kind help once again.

Regards,

Boulbul

Why that? And why is it not shown in the code you posted? You simply have to put it in front of the [PSCustomObject].

Format cmdlets in general are meant to be used for display purposses in the console only. And they have limits. With more than 10 properties to show it does not make that much sense to display that in a console anyway. … unless you have a very very wide screen. :wink:

That’s the worst idea ever. Format cmdlets destroy the powerful and rich objects and produce stupid boring pixels on the screen. Their output is not meant to be piped anywhere.

Instead you can pipe the output directly to Export-Csv or - if you install the great module from Doug Finke ImportExcel - to Export-Excel what results in a proper already formatted Excel sheet. :+1:t4: :wink:

Olaf,

Hi, Thank you once again…Your advice worked with a charm :grinning:… the [PSCustomObject] was so simple to use… I know understands much better the use of this command…I have managed to export all output via the module exportExcel, however…All output from the variable “Nic_IPAddresses” , “VM_HD_Size” & " VM_HD_Location" are ether empty or have a value of “stem.string” in them.

Here is the Code:

Get-VM | 
ForEach-Object {
    $VM = $_  # this variable assignment makes the current pipeline object available inside the nested loop
    $NicList = $_.NetworkAdapters
    foreach ($Nic in $NicList) {
        [PSCustomObject]@{
            ComputerName      = $VM.ComputerName
            Host_OS           = (Get-WMIObject win32_operatingsystem).caption #|Select "Local Area Connection* 1" 
            Host_IP           = (Get-NetAdapter ) 
            #Host_IP          = (Get-NetIPAddress  -AddressFamily IPv4 -InterfaceAlias "Local Area Connection* 1" |select -Property IPAddress)
            Nic_IPAddresses   = $Nic.IPAddresses 
            VM_Name           = $VM.Name
            Nic_MacAddress    = $Nic.MacAddress
            VM_CreationTime   = $VM.CreationTime
            VM_MemoryAssigned = $VM.MemoryAssigned # to write in MB
            VM_ID             = $VM.VMId
            VM_HD_Size        = $VM.VMId |Get-VHD| select Size , {$_.Size /1GB} # to filter this output in order to get just VM_HD_Location
            VM_State          = $VM.State
            Nic_Name          = $Nic.Name
            VM_HD_Location    = $VM.VMId |Get-VHD | Select Path # to filter this output in order to get just VM_HD_Location
            
        }
    }
} | Export-Excel -Path C:\temp\allvms.xls

Here are both output from the script and redirection onto the excel file.

Script output:

ComputerName      : Boulbul
Host_OS           : Microsoft Windows 10 Professionnel
Nic_IPAddresses   : {169.254.12.49, fe80::d13c:2319:ac06:c31}
VM_Name           : DCVM
Nic_MacAddress    : 00155D6A2A03
VM_CreationTime   : 21/08/2022 13:02:55
VM_MemoryAssigned : 771751936
VM_ID             : 81de770f-54cb-4d1a-beed-097e0cc1155a
VM_HD_Size        : @{Size=128849018880; $_.Size /1GB=120}
VM_State          : Running
Nic_Name          : Carte réseau
VM_HD_Location    : @{Path=C:\Users\Boulbul\Documents\Hyper-v\test1\test1_2017231E-A852-4812-9505-18843E929DC5.avhdx}

ComputerName      : Boulbul
Host_OS           : Microsoft Windows 10 Professionnel
Nic_IPAddresses   : {}
VM_Name           : Nouvel ordinateur virtuel
Nic_MacAddress    : 00155D6A2A06
VM_CreationTime   : 23/08/2022 16:24:47
VM_MemoryAssigned : 1073741824
VM_ID             : c1b89c96-d5a5-4c61-b63c-232d2133f192
VM_HD_Size        : 
VM_State          : Running
Nic_Name          : Carte réseau
VM_HD_Location    : 

ComputerName      : Boulbul
Host_OS           : Microsoft Windows 10 Professionnel
Nic_IPAddresses   : {169.254.119.5, fe80::bcb4:2f:f8df:7705}
VM_Name           : test2
Nic_MacAddress    : 00155D6A2A04
VM_CreationTime   : 21/08/2022 13:03:29
VM_MemoryAssigned : 824180736
VM_ID             : 83551f8f-59e3-4681-bf5d-0f76c940a333
VM_HD_Size        : @{Size=128849018880; $_.Size /1GB=120}
VM_State          : Running
Nic_Name          : Carte réseau
VM_HD_Location    : @{Path=C:\Users\Boulbul\Documents\Hyper-v\test2\test2_1CBB8966-2F01-469F-B8AE-AB55CECE8650.avhdx}

Output from excel file:

I suspect it has to do with the “{}” and “@{}” characters which are ignored by Excel, in my opinion. A hint on how to remove them, please.

Also, is there a way to retrieve IPv4 separately and then have both Ipv4 and IPv6 on one line.

Thank you for your help once again.

Kind regards,

Boulbul

For your VHD issue you can do it like this:

Get-VM | 
ForEach-Object {
    $VM = $_
    $NicList = $_.NetworkAdapters
    $VM_HD = $VM.VMId | Get-VHD
    foreach ($Nic in $NicList) {
        [PSCustomObject]@{
            VM_HD_Location = $VM_HD.Path
            VM_HD_Size     = ( $VM_HD.Size / 1GB )
        }
    }
}

There is always a way. But it depends on the existing conditions. If your VMs ALWAYS have only one IPv4 and one IPv6 address on their NICs you could do something like this:

Get-VM | 
ForEach-Object {
    $VM = $_
    $NicList = $_.NetworkAdapters
    foreach ($Nic in $NicList) {
        [PSCustomObject]@{
            ComputerName            = $VM.ComputerName
            Nic_FirstIPAddresseIPv4 = $Nic.IPAddresses[0]
            Nic_FirstIPAddresseIPv6 = $Nic.IPAddresses[1]
        }
    }
}

If there are more than one IPv6 addresses what’s not unusual they would be missing.

To get all possible IP addresses you could use

            Nic_IPAddresses         = $Nic.IPAddresses -join ', '

and of course you can do both if you want. :wink:

Hello again, I hope I’m not disturbing too much…

  1. I now realized that it was tedious to include the host IP addresses in the script, knowing that each server would have many interfaces with different IP addresses. I will leave this task for the end.

  2. I ran the script on some servers instead of my workstation (test platform). Although the OS is the same on all servers, I got a different result on a few!

With the VM_HD_Size, I get an error related to “Op_Devision”. Although there is an error, the script manages to get the data and write it to the Excel file on some servers, but not on others…It also moves duplicates IPv4 on both Nic_IPAddressesV4, Nic_IPAddressesV6 fields.

Here is the error I got.

I have commented this variable for the moment.

  1. For the VM_HD_Location it works fine, but it adds other columns in the excel file which are not really needed. Is there anyway retrieve only the disk location please?

You will also notice in the picture of excel output (next post) that on some cells I got “System.Collections.ArrayList” value instead of the disk location!

Here is the code:

#https://www.powershellgallery.com/packages/ImportExcel/7.8.0
Install-Module -Name ImportExcel
#forum
Invoke-Command -ComputerName  SRV1,SRV2 -Credential boulbul -ScriptBlock   {
Get-VM | 
ForEach-Object {
    $VM = $_  # this variable assignment makes the current pipeline object available inside the nested loop
    $NicList = $_.NetworkAdapters
    $VM_HD   = $VM.VMId  | Get-VHD
    foreach ($Nic in $NicList) {
        [PSCustomObject]@{
            ComputerName      = $VM.ComputerName
            Host_OS           = (Get-WMIObject win32_operatingsystem).caption #|Select "Local Area Connection* 1" 
            Nic_IPAddressesV4 = $Nic.IPAddresses[0]
            Nic_IPAddressesV6 = $Nic.IPAddresses[1]
            #Nic_AllIPadresses = $Nic.IPAddresses -join ', '
            VM_Name           = $VM.Name
            Nic_MacAddress    = $Nic.MacAddress
            VM_CreationTime   = $VM.CreationTime
            VM_MemoryAssigned = ($VM.MemoryAssigned  / 1GB)# to write in MB
            VM_ID             = $VM.VMId
            VM_HD_Size        = ($VM_HD.Size  / 1GB)
            VM_Status          = $VM.Status 
            VM_HD_Location    = $VM_HD.Parent[1]  # to filter this output in order to get just VM_HD_Location
            
        }
    }
} #| Export-Excel -Path C:\temp\allvms.xls
# Export the output to a CSV file. Change the file path accordingly.
} | Export-Excel -Path C:\temp\allVM.xls
    
  1. Would it be possible to have the VM operating system, and the VM Operating System Name? Please give me hint? Thank you, and my apologies for the many questions :slight_smile:

Regrards,

Boulbul

This is what was output onto the excel file:

Hmmm … actually you’re not querying the host IP addresses. At least not with the code you shared so far. But each VM can have multiple NICs as well and every single NIC can have multiple IPv4 and / or IPv6 addresses. You will have to make a decission what and how to display this in your data. You are actually trying to show hierarchical data in a structrured representation.

The way you did is wrong. You querying the OS of the computer the script runs on. That’s why you get the same result again and again. :wink:
Again - you should always read the help for the cmdlets you’re about to use … completely incuding the examples.
Instead of Get-WmiObject you should use

Example 7 shows how to query a remote computer. And the query should be outside of the inner loop.

Please do not post images of code or error messages or console output. Instead post the plain text and format it as code. :point_up_2:t4:

The extra columns are not from the VHD_Location. They are from the remote execution in general. When you read the help for

you can see that you can hide the computername with the parameter -HideComputerName

If you have more than one VHD connected to a VM you have to either use another nested loop or concatenate the VHDs to one data cell to be shown correctly in your Excel sheet.

Again - you’re trying to show hierarchical data in a structured manner!!! :point_up_2:t4: :point_up_2:t4:

$ComputerName =
'SRV1',
'SRV2'

$Result =
Invoke-Command -ComputerName $ComputerName -HideComputerName -ScriptBlock {
    $HostOS = Get-CimInstance -ClassName CIM_OperatingSystem
    Get-VM | 
    ForEach-Object {
        $VM = $_  
        $NicList = $VM.NetworkAdapters
        $VM_HD = $VM.VMId  | Get-VHD
        foreach ($Nic in $NicList) {
            [PSCustomObject]@{
                HostComputerName  = $ENV:COMPUTERNAME
                Host_OS           = $HostOS.caption
                Nic_IPAddressesV4 = $Nic.IPAddresses[0]
                Nic_IPAddressesV6 = $Nic.IPAddresses[1]
                VM_Name           = $VM.Name
                Nic_MacAddress    = $Nic.MacAddress
                VM_CreationTime   = $VM.CreationTime
                VM_MemoryAssigned = ($VM.MemoryAssigned / 1GB)
                VM_Status         = $VM.Status 
                VM_ID             = $VM.VMId
                VM_HD_Size        = $(foreach ($HD in $VM_HD) { ($HD.Size / 1GB) } ) -join ' || '
                VM_HD_Location    = ($VM_HD.Path) -join ' || '
            }
        }
    } 
} |
Select-Object -ExcludeProperty RunspaceId

$Result

Yes. BUT that’s going to be a little more complex the way you do it right now.
You are already running this script block against a remote computer. So you cannot remote into the next computer from inside of this script block. But you could use the result of this query as a source for a CIM query against all VMs directly outside of the first script block.

foreach ($VM in $Result) {
    $OS = Get-CimInstance -ClassName CIM_OperatingSystem -ComputerName $VM.VM_Name
    [PSCustomObject]@{
        VM    = $VM.VM_Name
        VM_OS = $OS.Caption
    }
}

Now you just have to add these newly queried information to the existing data. :wink:

1 Like

Thank you Olaf for your prompt reply.

I will perform some tests today and will get back to you…meanwhile, on another project, I have a number of clusters, on each cluster there are VMs hosted on a number of Nodes…I need to get the same result as above…with the exception of the loop to the clusters, would there be heavy modification to the script above?

Thank you.

Kind regards,

Boulbul

HI Again,

I actually run the code with nvoke-Command -ComputerName SRV1,SRV2... ; would not Get-WmiObject command run on each Hypervisor “SRV1,SRV2” instead of the machine I am running from the script?

Blockquote

It worked well…thank you.

does that mean that I have to run it with the invok ommand from the host server just like this?

$ComputerName =
'SRV1',
'SRV2'



$Result =
Invoke-Command -ComputerName $ComputerName -HideComputerName -ScriptBlock {

foreach ($VM in $Result) {
    $OS = Get-CimInstance -ClassName CIM_OperatingSystem -ComputerName $VM.VM_Name
    [PSCustomObject]@{
        VM    = $VM.VM_Name
        VM_OS = $OS.Caption
    }
}
}

I have tried running it directly after the above code and with inoke command, but did not work either way.

With the invoke command I got nothing on the output.

Without the invoke command I got the following:

Get-CimInstance : WinRM cannot process the request. The following error occurred while using Kerberos authentication: Cannot find the computer Win10-2022-01. Verify that the computer exists on the network and that the name provided is spelled 
correctly.
At line:35 char:11
+     $OS = Get-CimInstance -ClassName CIM_OperatingSystem -ComputerNam ...
+           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (root\cimv2:CIM_OperatingSystem:String) [Get-CimInstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x80070035,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand
    + PSComputerName        : Win10-2022-01

Thank you in advance.

Kind regards,

boulbul

You’re right. My mistake. Sorry. :pray:t3: I had still the initial version in mind where you run the code from the local machine.
Anyway - you should move this query out of the inner loop to not query this information several times. And you should not use Get-WmiObject anymore. :wink:

Cool. :+1:t3:

No. That wouldn’t work. You cannot run a command on a remote computer and remote from there to a third computer. That’s called double hop and it is not allowed by default.

Since you use Get-CimInstance and its built in abilty to query remote computers you should run this code from the local computer you use to run the other code. … so without Invoke-Command and the script block.

Some of your VMs may not run. So you need to determine before querying if they’re online or not. You can use an if condition with Test-Connection in advance.

Thank you for your response.

What I cannot understand is that all the VMs are working and I am getting the same errors as above for all of them. what is even more confusing, is that the VM value points to the VM’ name and not the VM’ Operating System Name… Please refer to the following output again (My apoligies, I have not entered the correct output above, this is the right one)…

Get-CimInstance : WS-Management could not connect to the specified destination: (Microsoft Windows Server 2019 Standard:5985).
At line:41 char:11
+     $OS = Get-CimInstance -ClassName CIM_OperatingSystem -ComputerNam ...
+           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (root\cimv2:CIM_OperatingSystem:String) [Get-CimInstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x80072ee5,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand
    + PSComputerName        : Microsoft Windows Server 2019 Standard
 
VM    : Win10-2022-01
VM_OS : 

See…under VM it is reffering to the VM name and not its operating system name …cause the name under the OS is different, and it should have someting else…unless I have badly explained myself in my request? and there is no value under VM_OS? any hints please.

Thanks a lot

Kind regards,

Boulbul

To debug your code you run it line by line and just for one VM and inspect the output in the console. If the code works as needed for one computer you take the next step and so on.

Of course. The name of the VM comes from the input data and is available. The OS comes from the query inside the loop. And because that query does not work you don’t have a result. Logic, isn’t it? :wink:

What? :thinking: :face_with_raised_eyebrow: :woozy_face:

Check the code with only ONE computer at first:

$VM = 'Remote Computer'
$OS = Get-CimInstance -ClassName CIM_OperatingSystem -ComputerName $VM
[PSCustomObject]@{
    VM             = $VM
    VM_OS          = $OS.Caption
    LastBootUpTime = $OS.LastBootUpTime
}

Hello Olaf,

I got the same result as above when I run it from a management server.

Running it from the hypervisor directly yelded the following:

Get-CimInstance : WinRM cannot process the request. The following error with errorcode 0x8009030e occurred while using Kerberos authentication: A specified logon session does not exist. It may already have been 
terminated.  
 Possible causes are:
  -The user name or password specified are invalid.
  -Kerberos is used when no authentication method and no user name are specified.
  -Kerberos accepts domain user names, but not local user names.
  -The Service Principal Name (SPN) for the remote computer name and port does not exist.
  -The client and remote computers are in different domains and there is no trust between the two domains.
 After checking for the above issues, try the following:
  -Check the Event Viewer for events related to authentication.
  -Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTTPS transport.
 Note that computers in the TrustedHosts list might not be authenticated.
   -For more information about WinRM configuration, run the following command: winrm help config.
At line:2 char:7
+ $OS = Get-CimInstance -ClassName CIM_OperatingSystem -ComputerName $V ...
+       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (root\cimv2:CIM_OperatingSystem:String) [Get-CimInstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x80070520,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand
    + PSComputerName        : Win10-2022-01

Just to let you know that the credentials to access the hypervisor is not the same as the once for the VM…wouldn’t this cause any problem? but then I thought that VMs can communicate some information directly without the need have credentials?

I will try to be clearer here… Each computer has a name ( this is what I refer to by the OS name). And each VM has a name too.

Your code managed to get the VM name with no probme (Win10-2022-01)…What I also asked for is for the name that was given to the VM (E.g: Boulbul) when installing the operating system.

If you think that it hard to do, let’s not worry about it…Thank you so much for your help.

Kind regards,

Boubul

Ahhhh … now I see … :roll_eyes: :wink: … that adds another complexity layer on top of the already existing ones.

I think a better name for OS name would be hostname. OS name usually would be “Windows Server 2019” or something like this.

I actually never worked with an environment like this. All our servers have the same hostname like their VM.

Of course you need to use the hostnames of the VMs to access them with Get-CimInstance and not the VM names. You could try to resolve the IP addresses you determined with the query before to the according hostnames and use these for the further steps.

And of course you need to have sufficient rights to access the target computers with Get-CimInstance.

Thank you Olaf, I will stop here for this request… …OOOH., how can I forget the “hostname”… :face_with_hand_over_mouth:…I think that this would be more than enough…You assistance was great, and would not have been possible to get to this stage without your aid.

This is the final code for those who find it usefull

#https://www.powershellgallery.com/packages/ImportExcel/7.8.0
Install-Module -Name ImportExcel

#Assign the username to the viariable.
$Identifiant = 'Boulbul'

#Assign the computer names to the viriable.
$ComputerName =  'SRV01','SRV02','SRV03'


#Retrieve the details
$Result =
Invoke-Command -ComputerName $ComputerName -HideComputerName -Credential $Identifiant -ScriptBlock {
    $HostOS = Get-CimInstance -ClassName CIM_OperatingSystem
    Get-VM | 
    ForEach-Object {
        $VM = $_  
        $NicList = $VM.NetworkAdapters
        $VM_HD = $VM.VMId  | Get-VHD
        foreach ($Nic in $NicList) {
            [PSCustomObject]@{
                HostComputerName  = $ENV:COMPUTERNAME
                Host_OS           = $HostOS.caption
                Nic_IPAddressesV4 = $Nic.IPAddresses[0]
                Nic_IPAddressesV6 = $Nic.IPAddresses[1]
                VM_Name           = $VM.Name
                Nic_MacAddress    = $Nic.MacAddress
                VM_CreationTime   = $VM.CreationTime
                VM_MemoryAssigned = ($VM.MemoryAssigned / 1GB)
                VM_ID             = $VM.VMId
                VM_HD_Size        = $(foreach ($HD in $VM_HD) { ($HD.Size / 1GB) } ) -join ' || '
                VM_HD_Location    = ($VM_HD.Path) -join ' || '
            }
        }
    } 
} |
Select HostComputerName, Host_OS, Nic_IPAddressesV4,Nic_IPAddressesV6, VM_Name, Nic_MacAddress, VM_CreationTime, VM_MemoryAssigned, VM_ID, VM_HD_Size, VM_HD_Location

#export the result to an excel file.
$Result  |  Export-Excel -Path C:\temp\allVM.xls

Olaf, I have another request that is related to clusters…I will search first if I cannot find the answer, I will post it onto another post if you don’t mind.

Until then, have a nice weekend.

Kind regards,

Boulbul

Since PowerShell automatically loads needed modules anyway I’d use

#Requires -Modules ImportExcel

That would prevent the script from running if the needed module is not available on the computer the script runs on. :wink:

Here you can read more about the #Requires statement