Scripting Hyper-V with WMI and PowerShell: Part 1 – Introduction + Querying State

Scripting Hyper-V with WMI and PowerShell

Part 1 – Introduction + Querying State



When it comes to scripting Hyper-V there are really 2 methods:

1. Using the virtualization WMI provider that ships with Hyper-V.

2. Using the cmdlets provided by System Centre Virtual Machine Manager 2008

So which option should you use? Well if you want an easy life, the answer is absolutely Option 2. Use SCVMM 2008, and scripting Hyper-V is like a pleasurable dream. The cmdlets are task orientated, provide a rich set of features and really do work very well. So why is this a guide to Option 1 – Using the virtualization WMI provider? Well, sometimes Hyper-V will be used without an accompanying System Centre deployment, and if that’s the case, using WMI is your only scripting option.

I`ll be honest, using the WMI provider to script Hyper-V is unintuitive, complicated and feels quite clunky. So the question has to be asked “Why is the Hyper-V WMI provider so difficult to use?” The answer is Industry Standards. The virtualization WMI provider fully complies with the standards outlined by the Distributed Management Task Force (DMTF). Whilst standards are great for creating consistency among different vendors, there are often comprises with the simplicity of individual solutions. Contrastingly the SCVMM cmdlets are a bespoke solution designed by Microsoft to be simple, intuitive and powerful, but do not adhere to any industry standards.

So, with the expectation that the Hyper-V WMI journey will be a challenging one, let’s get on with it.


WMI Basics

As mentioned we will be using the virtualization WMI provider, and before going any further I would strongly recommend that you spend some time understanding WMI to a reasonable depth. If you can answer the following questions, you’re probably familiar enough with WMI to get the most out of this tutorial:

1. What is namespace?

2. What is a class?

3. How do you create a WMI Object in PowerShell?

Basic WMI information is out of scope for this tutorial, so if you can’t answer the above questions, before continuing I would suggest the following pre-reading/viewing:

1. Brief WMI Intro on Technet Edge -

2. Windows, PowerShell and WMI – Tech Ed 2008 Session


3. Microsoft Windows PowerShell Step by Step Book-


Hyper-V + WMI

There are 2 key points you need to understand to start using the Hyper-V WMI provider.

1. All Hyper-V classes live in the “Virtualization” namespace. Therefore whenever you want to instantiate an object you need to specify this namespace. The following sample lists all the classes available in this namespace:

Get-WMIObject –namespace “root\virtualization” -list


2. PowerShell must be elevated and running as an administrator. If you run PowerShell in a non-administrative context you will not be able to connect to any guests, and will only be able to affect the host. In Server 2008 you need to right-click the PowerShell icon, then click “Run As Administrator” to achieve this, even if logged on as an administrator.


Often, I find the best way to learn something is with a worked example. Attached to this post is VMStateQuery.ps1, which is an example PowerShell script which can be used to determine the state of guests deployed to a Hyper-V host. The script can be used to return the state of all guests on a host, or the state of 1 particular guest.



This returns a list of all guests and their state, sorted alphabetically.

.\VMStateQuery.ps1 -vhost myremotehost -sortbystate

This returns a list of all the guests on MyRemoteHost, and sorts the guests by state.

.\VMStateQuery.ps1 –vhost myremotehost –vguest MyGuest1

This returns the state of the guest MyGuest1, running on the host MyRemoteHost.


Let’s dig into some interesting parts of this script.

The only time we use WMI in this example is in this 1 line:

$vms = Get-WMIObject -Class Msvm_ComputerSystem -Namespace "root\virtualization" -ComputerName $vhost


This line connects using WMI and retrieves all instances of MSVM_ComputerSystem on the computer specified by $VHost. This line returns an array of all guests and the host, each one represented by an object. In order to find out what we can with this object type we can do two things. Firstly, use Get-Member to obtain all properties and methods, or use this MSDN link, which details each property and method.

Having looked at the properties of this object we can see 2 properties that will be particularly useful when trying to query a guest’s state: elementname and enabledstate. ElementName is the name of the guest that you see in the Hyper-V MMC console, and enabledstate is a number that represents the state of the machine.

This bit of code filters our array of guests, and returns any that match the following

$vms = $vms | where-object {$_.elementname -eq $vguest}


We simply use where-object to filter, such that only guests whose elementname equals $vguest are retained.

We use the enabledstate property to identify the state of the machine. However, the state of the machine is a number which might not make too much sense. Therefore I’ve created a function called ConvertStateToFriendly which simply uses a switch statement to return a friendly word for the state. The call to this function is nested as an expression that can be used by the format-table cmdlet to display the information nicely. Here’s the code:

$statefriendly = @{Expression={convertStateToFriendly $_.enabledstate};Label="State";width=25}

$vms | format-table Elementname, $statefriendly


This code looks a little bid nasty, but is simply a way of creating custom tables. More details on how this mechanism works can be found here.

One final part I want to explain is this line:

$vms = $vms | where-object{$_.caption -ne "Hosting Computer System"}


When you get all instances of MSVM_ComputerSystem, one of the returned objects represents the host system. In this script I am not really interested in the state of the host, just the state of the guests. Therefore the above line simply looks at the caption property of the objects, and drops the object with the name “Hosting Computer System”.

All the rest of the script is generic PowerShell code, used for parameters, error checking and other useful bits and pieces.

Hyper-V WMI Resources

The two best resources for Hyper-V WMI scripting that I have come across so far are the MSDN page, and James O’Neil’s Hyper-V management library on CodePlex. The MSDN page is the definitive source on the WMI provider and is here:

The Code Plex project which James uploaded is a pretty comprehensive library on managing Hyper-V and WMI. It’s an excellent source, but be warned it is pretty hardcore and very code efficient in places, which can sometimes be quite tricky to understand (maybe that’s just me J)


My colleague Richard Macdonald has written a very similar script, but using C# instead of PowerShell. Check out his blog here for the code.

Well that’s it for part 1. Stay tuned for Part 2 –Hyper-V Data Gathering.