Scripts to Inventory Virtual Machines [Hyper-V]

Scripts to Inventory Virtual Machines [Hyper-V]

  • Comments 6


Someone asked me if it was possible to make a script that would tell you what guest operating systems you had running on a Hyper-V server.  To answer them I whipped up two sample PowerShell scripts.

The first one will generate a table of detected guest operating systems – and a count for each type – as well as showing you how many offline virtual machines exist on the computer:

# Prompt for the Hyper-V Server to use
$HyperVServer = Read-Host "Specify the Hyper-V Server to use (enter '.' for the local computer)"
 
# Get all virtual machine objects on the server in question
$VMs = gwmi -namespace root\virtualization Msvm_ComputerSystem -computername $HyperVServer -filter "Caption = 'Virtual Machine'" 
 
# Create an empty hashtable
$table = @{}
 
# Go over each of the virtual machines
foreach ($VM in [array] $VMs) 
  {
   # Get the KVP Object
   $query = "Associators of {$VM} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"
   $Kvp = gwmi -namespace root\virtualization -query $query -computername $HyperVServer
 
   # Get the OSName value out of the guest KVP data
   $xml = [xml]($Kvp.GuestIntrinsicExchangeItems | ? {$_ -match "OSName"})
   $entry = $xml.Instance.Property | ?{$_.Name -eq "Data"}
 
   # Filter out offline virtual machines and virtual machines which did not return KVP data
   if ($entry.Value) 
      {$value = $entry.Value}
   elseif ($VM.EnabledState -ne 2)
      {$value = "Offline"}
   else {$value = "Unknown"}
 
   # Count up the values and store it in a hashtable
   if ($table.ContainsKey($value)) 
      {$table[$value] = $table[$value] + 1 }
   else
      {$table[$value] = 1}
   }
 
# Display the results in a nicely formated and sorted manner
$table.GetEnumerator() | Sort-Object Name | Format-Table -Autosize

This script will products an output like this:

image

Then I made a simpler, more “light weight”, script that will return the same information – but does not include offline virtual machines:

# Prompt for the Hyper-V Server to use
$HyperVServer = Read-Host "Specify the Hyper-V Server to use (enter '.' for the local computer)"
 
# Get all guest KVP data objects on the server in question
$Kvps = gwmi -namespace root\virtualization Msvm_KvpExchangeComponent -computername $HyperVServer
 
# Create an empty hashtable
$table = @{}
 
# Go over each of the guest KVP data objects
foreach ($Kvp in [array] $Kvps) 
  {
   # Get the OSName value out of the guest KVP data
   $xml = [xml]($Kvp.GuestIntrinsicExchangeItems | ? {$_ -match "OSName"})
   $entry = $xml.Instance.Property | ?{$_.Name -eq "Data"}
 
   # Filter out unknown operating systems
   if ($entry.Value) {$value = $entry.Value} else {$value = "Unknown"}
 
   # Count up the values and store it in a hashtable
   if ($table.ContainsKey($value)) 
      {$table[$value] = $table[$value] + 1 }
   else
      {$table[$value] = 1}
   }
 
# Display the results in a nicely formated and sorted manner
$table.GetEnumerator() | Sort-Object Name | Format-Table -Autosize

This script produces an output like this:

image

Both of these scripts use the guest operating system data that is returned through the Hyper-V key-value pair functionality to identify what is present on your system. 

The big difference between the two scripts is that the first one starts by identifying all the virtual machines on the physical computer – and then finding the key-value pair data associated with that virtual machine.  This means that it is able to identify offline virtual machines (which do not return guest key-value pair data).  But it also means that the script will take longer to run on a system with a lot of virtual machines.  Meanwhile, the second script just grabs all the guest key-value pair objects on the system and does not attempt to associate them with virtual machines.  This approach is much quicker – but will not account for offline virtual machines.

Cheers,
Ben

Leave a Comment
  • Please add 5 and 5 and type the answer here:
  • Post
  • Awesome, thanks for this post!

  • Hi Ben,

    Cool script! I started playing around with the code and ended up with something even faster :D

    http://mindre.net/post/Retrive-a-list-of-virtual-machines-in-Hyper-V-with-PowerShell.aspx

  • Tore -

    Neat! Yes, using GetSummaryInformation would be faster.  The fact is that this method exists solely to give our MMC snapin a fast way to gather a lot of information about a lot of virtual machines.

    Cheers,

    Ben

  • I use a similar script to put that info into BGinfo running on the host. However my problem lies in the inverse.

    Is there anyway to find from the guest which host it is running on?

  • Can it be modified to include the RAM present on each machine and location of VHD file in use...?

  • Can anyone help me to create "Scripts to Inventory Virtual Machines with statsu, OS, RAM, vCPU, vhdx and location on CSV on hyper-v Cluster"

Page 1 of 1 (6 items)