Programming Hyper-V with WMI and C# - Getting Started

You may have seen from a recent post that I received a new laptop that was capable of running Hyper-V.  Well, it's all fully installed and working, so I thought I might blog about it a bit.  There are plenty of existing blogs on Hyper-V, so I thought I might take a slightly different tack and look at coding for Hyper-V in C#. 

This suits me fine as I like to get to know new software technologies via their API - I think it really helps to understand the features and what you can do with a technology if you have to write some code using it.  You may think differently, depending on how much coding you do - if you are more of a scripter, then check out my colleague, Ben Pearce's blog, where he does a similar thing to what I'm doing here, but using PowerShell.

Anyway, Hyper-V provides a nice interface for scripting and programming.  The interface is usable from any scripting/coding language that can access WMI.  For example: VBScript, C++, PowerShell, C#, etc.  In this short tutorial I'll look at connecting and querying via C#, but the techniques can be easily adapted to the language of your choice.

UPDATE: After posting I realised I'd made a classic dev mistake: I wrote and tested the code while logged in with an account with administrative rights on the Hyper-V server, and just assume you'd do the same If you have any access problems make sure you use an appropriate account. Some references to help with setting that up:

Connecting to WMI on a Remote Computer

Hyper-V Remote Management: You do not have the requested permission to complete this task. Contact the administrator of the authorization policy for the computer ‘COMPUTERNAME’

Basic Connection

WMI is the Microsoft implementation of WBEM and has been around since Windows 2000, so you may already be familiar with it from scripting, etc.  If you've used it in C# before, then even better - working with Hyper-V will be a breeze for you.

For this example, we will need to use the Msvm_ComputerSystem class.  This class gives details of a Hyper-V host or virtual machine, including the "state" (i.e. is it running, paused, etc), "runtime" (how long has it been executing), etc.

Using this class, we can easily connect to the local system and grab a list of the VMs.  The important WMI bits are these:

 // add this namespace in order to access WMI
// also need to add a reference to System.Management.dll
using System.Management;

// we want to connect locally (".") to the Hyper-V namespace ("root\virtualization")
ManagementScope manScope = new ManagementScope(@"\\.\root\virtualization");

// define the information we want to query - in this case, just grab all properties of the object
ObjectQuery queryObj = new ObjectQuery("SELECT * FROM Msvm_ComputerSystem");

// connect and set up our search
ManagementObjectSearcher vmSearcher = new ManagementObjectSearcher(manScope, queryObj);
ManagementObjectCollection vmCollection = vmSearcher.Get();

// loop through the machines
foreach (ManagementObject vm in vmCollection)
{
    // display VM details
    Console.WriteLine("\nName: {0}\nStatus: {1}\nDescription: {2}\n",
                        vm["ElementName"].ToString(),
                        vm["EnabledState"].ToString(),
                        vm["Description"].ToString());
}

The above code will connect to the local Hyper-V system and pull out details for the host and all VMs.  To connect to a remote system, simply change the management scope:

ManagementScope manScope = new ManagementScope(@"\\RemoteSystem\root\virtualization");

Where "RemoteSystem" is the name of the remote Hyper-V system to manage.

   

I'm Not Me, I'm Him

The above sample can connect locally and remotely (depending on the scope) and in both cases, it simply uses the credentials of the logged-on user.  However, in the remote case, it is possible to supply alternate credentials to use.  It is a little more work, but not much:

 // add this namespace in order to access WMI
// also need to add a reference to System.Management.dll
using System.Management;

// define the information we want to query - in this case, just grab all properties of the object
ObjectQuery queryObj = new ObjectQuery("SELECT * FROM Msvm_ComputerSystem");

// object for storing WMI connection options
// pass the "user", "password" and "domain" from command-line
// don't hard-code these into the application!
ConnectionOptions connOpts = new ConnectionOptions();
connOpts.Username  = user;
connOpts.Authority = "ntlmdomain:" + domain;
connOpts.Password  = password;

// management scope object
ManagementScope manScope = new ManagementScope(@"\\RemoteSystem\root\virtualization", connOpts);

// connect and set up our search
ManagementObjectSearcher vmSearcher = new ManagementObjectSearcher(manScope, queryObj);
ManagementObjectCollection vmCollection = vmSearcher.Get();

// loop through the VMs
foreach (ManagementObject vm in vmCollection)
{
    // display VM details
    Console.WriteLine("\nName: {0}\nStatus: {1}\nDescription: {2}\n",
                      vm["ElementName"].ToString(),
                      vm["EnabledState"].ToString(),
                      vm["Description"].ToString());
}

Trying to use alternate credentials locally will result in an exception.

So, that's it for basic connecting and querying the machines on a Hyper-V system.  For a more complete sample that implements the above code in a more realistic way, grab the download below.

Code Sample

Download a complete working code sample here:

VMStateQuery Code

VMStateQuery is a command-line tool that implements the code snippets discussed above.  Compile in Visual Studio, then use like this:

VMStateQuery [-vhost remoteserver] [-user domain\user] [-pwd password] [-vguest guest] [-sortbystate]

Where:

-vhost remoteserver specifies the remote hyper-v server to manage
-user specifies the domain\user to connect as
-pwd password password for the specified user account
-vguest guest query the state of a specific virtual machine
-sortbystate sort the output by the state of the machine

Typical output looks like this:

vmsqout

References

Windows Management Instrumentation Documentation

System.Management Namespace

Virtualization WMI Provider