Create VM (Hyper-V) via code - .NET version Create VM programmatically
[Sergei Meleshchuk. http://blogs.msdn.com/sergeim/]
It looks everyone likes PowerShell, and for Hyper-V management in particular.
Sometimes I feel more traditional languages (like C#) give more control/error handling. Another C# benefit is what I think is unsurpassed tracing and debugging facilities of Visual Studio (especially if to forget WinDbg for a second). Sometimes you can learn API by just stepping thru the code.
Here below is the PS1 à C# port of some code written originally by James O’Neill. I might have changed something a little, no offence taken.
I briefly 1) outline needed steps, 2) comment code fragments and 3) provide full code. Add System.Management.dll to references, and start the VS elevated (that is, right-click, select ‘run as administrator).
The steps are:
- Get parameters from command line
- Obtain the “MsVM_VirtualSystemManagementService” object, which will do all the work for us. I will call it VSMS for brevity.
- Step 1. Ask VSMS to create a sort of empty VM definition. I think about this thing as of a template.
- Step 2. Obtain set of VM settings; fill in those settings
- Step 3. Modify the newly created ComputerSystem (sort of template) with the settings we just prepared.
First, some abbreviations I use:
using MO = ManagementObject;
using MBO = ManagementBaseObject;
using MOS = ManagementObjectCollection;
Trick here is a late-bound call on VSMS; see how managed WMI calls are coded (search for WMI InvokeMethod). The code is:
// Create VM with empty settings
MBO definition = sysMan.InvokeMethod(
Constants.DefineVirtualSystem,
sysMan.GetMethodParameters(Constants.DefineVirtualSystem), // empty set
null);
uint retCode = (uint)definition["returnvalue"];
if (retCode != Constants.ERROR_SUCCESS)
throw new InvalidOperationException("DefineVirtualSystem failed");
Next we get the WMI’s ManagementObject, which represents the instance of MSVM_ComputerSystem WMI class:
string vmPath = definition["DefinedSystem"] as string;
MO computerSystemTemplate = new MO(vmPath);
At this point, we are half-done.
First, get the generated VM name, which is actually a GUID (the display name is called ‘elementname’ in Hyper-V API world). Then we locate the ‘settings’ object:
string vmName = (string)computerSystemTemplate["name"];
// this is GUID; will need to locate settings for this VM
MO settings = GetMsvm_VirtualSystemSettingData(vmName);
Now fill in the settings object:
// Now, set settings of this MSVM_ComputerSystem as we like
settings["elementname"] = displayName;
settings["notes"] = notes;
settings["BIOSGUID"] = new Guid();
settings["BIOSSerialNumber"] = "1234567890";
settings["BIOSNumLock"] = "true";
// settings["..."] = ...;
// ... set whatever you like; see list at
// http://msdn.microsoft.com/en-us/library/cc136944(VS.85).aspx
settings.Put();
Use VSMS (management service) again to propagate settings to VM object.
// Now, set the settings which were build above to newly created ComputerSystem
MBO inParams = sysMan.GetMethodParameters(Constants.ModifyVirtualSystem);
string settingsText = settings.GetText(TextFormat.WmiDtd20);
inParams["ComputerSystem"] = computerSystemTemplate;
inParams["SystemSettingData"] = settingsText;
MBO resultToCheck = sysMan.InvokeMethod(
Constants.ModifyVirtualSystem,
inParams,
// Almost done - now apply the settings to newly created ComputerSystem
MO settingsAsSet = (MO)resultToCheck["ModifiedSettingData"];
// Optionally print settingsAsSet here
Log("Created: VM with name '{0}' and GUID name '{1}'", displayName, vmName);
CreateVm
Useful functions (to be coded once) are:
#region Wmi Helpers
private MO GetWmiObject(string classname, string where)
{
MOS resultset = GetWmiObjects(classname, where);
if (resultset.Count != 1)
throw new InvalidOperationException(
string.Format(
"Cannot locate {0} where {1}",
classname,
where));
MOS.ManagementObjectEnumerator en = resultset.GetEnumerator();
en.MoveNext();
MO result = en.Current as MO;
if (result == null)
throw new InvalidOperationException("Failure retrieving " + classname +
return result;
}
private MOS GetWmiObjects(string classname, string where)
string query;
ManagementScope scope = new ManagementScope(@"root\virtualization", null);
if (where != null)
query = string.Format(
"select * from {0} where {1}",
where);
else
CultureInfo.InvariantCulture,
"select * from {0}",
classname);
ManagementObjectSearcher searcher = new ManagementObjectSearcher(
scope,
new ObjectQuery(query));
ManagementObjectCollection resultset = searcher.Get();
return resultset;
#endregion Wmi helpers
// This is port to C# from a Powershell script written by James O'Neill
using System;
using System.Globalization;
using System.Management;
namespace Hyperv.Misc
class MainCreateVm
static void Main(string[] args)
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(Oops);
new MainCreateVm().CreateVm(args);
void CreateVm(string[] args)
if (args.Length < 1)
Console.ForegroundColor = ConsoleColor.Red;
Log("Usage: createvm <vmname> [<notes>]");
Console.ForegroundColor = ConsoleColor.White;
Log("Example: createvm vm1");
Console.ResetColor();
Environment.Exit((int)Constants.ERROR_INV_ARGUMENTS);
string displayName = args[0];
string notes;
if (args.Length > 1)
notes = args[1];
notes = "Created " + DateTime.Now;
MO sysMan = GetMsVM_VirtualSystemManagementService();
// Obtain WMI root\virtualization:ComputerSystem object.
// we will need "Name" of it, which is GUID
} // CreateVm
private MO GetMsVM_VirtualSystemManagementService()
return GetWmiObject("MsVM_VirtualSystemManagementService", null);
private MO GetMsvm_VirtualSystemSettingData(string vmName)
return GetWmiObject(
"Msvm_VirtualSystemSettingData",
string.Format("systemname='{0}'", vmName));
throw new InvalidOperationException("Failure retrieving " + classname + " where " + where);
private static void Log(string message, params object[] data)
Console.WriteLine(message, data);
private static void Oops(object sender, UnhandledExceptionEventArgs e)
Console.BackgroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Black;
Exception ex = e.ExceptionObject as Exception;
Log(ex.Message);
Log(ex.ToString());
} // class MainCreateVm
class Constants
internal const string DefineVirtualSystem = "DefineVirtualSystem";
internal const string ModifyVirtualSystem = "ModifyVirtualSystem";
internal const uint ERROR_SUCCESS = 0;
internal const uint ERROR_INV_ARGUMENTS = 87;