Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The following utilities are used by some of the C# virtualization samples.
namespace Microsoft.Samples.HyperV.Common
{
using System;
using System.Globalization;
using System.Management;
using System.Threading;
using System.IO;
using System.Xml;
using System.Collections.Generic;
enum JobState
{
New = 2,
Starting = 3,
Running = 4,
Suspended = 5,
ShuttingDown = 6,
Completed = 7,
Terminated = 8,
Killed = 9,
Exception = 10,
CompletedWithWarnings = 32768
}
public static class VirtualSystemTypeNames
{
public const string RealizedVM = "Microsoft:Hyper-V:System:Realized";
public const string PlannedVM = "Microsoft:Hyper-V:System:Planned";
public const string RealizedSnapshot = "Microsoft:Hyper-V:Snapshot:Realized";
public const string RecoverySnapshot = "Microsoft:Hyper-V:Snapshot:Recovery";
public const string PlannedSnapshot = "Microsoft:Hyper-V:Snapshot:Planned";
public const string MissingSnapshot = "Microsoft:Hyper-V:Snapshot:Missing";
public const string ReplicaStandardRecoverySnapshot = "Microsoft:Hyper-V:Snapshot:Replica:Standard";
public const string ReplicaApplicationConsistentRecoverySnapshot = "Microsoft:Hyper-V:Snapshot:Replica:ApplicationConsistent";
public const string ReplicaPlannedRecoverySnapshot = "Microsoft:Hyper-V:Snapshot:Replica:PlannedFailover";
public const string ReplicaSettings = "Microsoft:Hyper-V:Replica";
}
public static class WmiUtilities
{
/// <summary>
/// Validates the output parameters of a method call and prints errors, if any.
/// </summary>
/// <param name="outputParameters">The output parameters of a WMI method call.</param>
/// <param name="scope">The ManagementScope to use to connect to WMI.</param>
/// <returns><c>true</c> if successful and not firing an alert; otherwise, <c>false</c>.</returns>
public static bool
ValidateOutput(
ManagementBaseObject outputParameters,
ManagementScope scope)
{
return ValidateOutput(outputParameters, scope, true, false);
}
/// <summary>
/// Validates the output parameters of a method call and prints errors, if any.
/// </summary>
/// <param name="outputParameters">The output parameters of a WMI method call.</param>
/// <param name="scope">The ManagementScope to use to connect to WMI.</param>
/// <param name="throwIfFailed"> If true, the method throws on failure.</param>
/// <param name="printErrors">If true, Msvm_Error messages are displayed.</param>
/// <returns><c>true</c> if successful and not firing an alert; otherwise, <c>false</c>.</returns>
public static bool
ValidateOutput(
ManagementBaseObject outputParameters,
ManagementScope scope,
bool throwIfFailed,
bool printErrors)
{
bool succeeded = true;
string errorMessage = "The method call failed.";
if ((uint)outputParameters["ReturnValue"] == 4096)
{
//
// The method invoked an asynchronous operation. Get the Job object
// and wait for it to complete. Then we can check its result.
//
using (ManagementObject job = new ManagementObject((string)outputParameters["Job"]))
{
job.Scope = scope;
while (!IsJobComplete(job["JobState"]))
{
Thread.Sleep(TimeSpan.FromSeconds(1));
//
// ManagementObjects are offline objects. Call Get() on the object to have its
// current property state.
//
job.Get();
}
if (!IsJobSuccessful(job["JobState"]))
{
succeeded = false;
//
// In some cases the Job object can contain helpful information about
// why the method call failed. If it did contain such information,
// use it instead of a generic message.
//
if (!string.IsNullOrEmpty((string)job["ErrorDescription"]))
{
errorMessage = (string)job["ErrorDescription"];
}
if (printErrors)
{
PrintMsvmErrors(job);
}
if (throwIfFailed)
{
throw new ManagementException(errorMessage);
}
}
}
}
else if ((uint)outputParameters["ReturnValue"] != 0)
{
succeeded = false;
if (throwIfFailed)
{
throw new ManagementException(errorMessage);
}
}
return succeeded;
}
/// <summary>
/// Prints the relevant message from embedded instances of Msvm_Error.
/// </summary>
/// <param name="job">The job from which errors are to be printed.</param>
public static void
PrintMsvmErrors(
ManagementObject job)
{
string[] errorList;
using (ManagementBaseObject inParams = job.GetMethodParameters("GetErrorEx"))
using (ManagementBaseObject outParams = job.InvokeMethod("GetErrorEx", inParams, null))
{
if ((uint)outParams["ReturnValue"] != 0)
{
throw new ManagementException(string.Format(CultureInfo.CurrentCulture,
"GetErrorEx() call on the job failed"));
}
errorList = (string[])outParams["Errors"];
}
if (errorList == null)
{
Console.WriteLine("No errors found.");
return;
}
Console.WriteLine("Detailed errors: \n");
foreach (string error in errorList)
{
string errorSource = string.Empty;
string errorMessage = string.Empty;
int propId = 0;
XmlReader reader = XmlReader.Create(new StringReader(error));
while (reader.Read())
{
if (reader.Name.Equals("PROPERTY", StringComparison.OrdinalIgnoreCase))
{
propId = 0;
if (reader.HasAttributes)
{
string propName = reader.GetAttribute(0);
if (propName.Equals("ErrorSource", StringComparison.OrdinalIgnoreCase))
{
propId = 1;
}
else if (propName.Equals("Message", StringComparison.OrdinalIgnoreCase))
{
propId = 2;
}
}
}
else if (reader.Name.Equals("VALUE", StringComparison.OrdinalIgnoreCase))
{
if (propId == 1)
{
errorSource = reader.ReadElementContentAsString();
}
else if (propId == 2)
{
errorMessage = reader.ReadElementContentAsString();
}
propId = 0;
}
else
{
propId = 0;
}
}
Console.WriteLine("Error Message: {0}", errorMessage);
Console.WriteLine("Error Source: {0}\n", errorSource);
}
}
/// <summary>
/// Gets the Msvm_ComputerSystem instance that matches the requested virtual machine name.
/// </summary>
/// <param name="name">The name of the virtual machine to retrieve the path for.</param>
/// <param name="scope">The ManagementScope to use to connect to WMI.</param>
/// <returns>The Msvm_ComputerSystem instance.</returns>
public static ManagementObject
GetVirtualMachine(
string name,
ManagementScope scope)
{
return GetVmObject(name, "Msvm_ComputerSystem", scope);
}
/// <summary>
/// Gets the Msvm_PlannedComputerSystem instance matching the requested virtual machine name.
/// </summary>
/// <param name="name">The name of the virtual machine to retrieve the path for.</param>
/// <param name="scope">The ManagementScope to use to connect to WMI.</param>
/// <returns>The Msvm_PlannedComputerSystem instance.</returns>
public static ManagementObject
GetPlannedVirtualMachine(
string name,
ManagementScope scope)
{
return GetVmObject(name, "Msvm_PlannedComputerSystem", scope);
}
/// <summary>
/// Gets the first virtual machine object of the given class with the given name.
/// </summary>
/// <param name="name">The name of the virtual machine to retrieve the path for.</param>
/// <param name="className">The class of virtual machine to search for.</param>
/// <param name="scope">The ManagementScope to use to connect to WMI.</param>
/// <returns>The instance representing the virtual machine.</returns>
private static ManagementObject
GetVmObject(
string name,
string className,
ManagementScope scope)
{
string vmQueryWql = string.Format(CultureInfo.InvariantCulture,
"SELECT * FROM {0} WHERE ElementName=\"{1}\"", className, name);
SelectQuery vmQuery = new SelectQuery(vmQueryWql);
using (ManagementObjectSearcher vmSearcher = new ManagementObjectSearcher(scope, vmQuery))
using (ManagementObjectCollection vmCollection = vmSearcher.Get())
{
if (vmCollection.Count == 0)
{
throw new ManagementException(string.Format(CultureInfo.CurrentCulture,
"No {0} could be found with name \"{1}\"",
className,
name));
}
//
// If multiple virtual machines exist with the requested name, return the first
// one.
//
ManagementObject vm = GetFirstObjectFromCollection(vmCollection);
return vm;
}
}
/// <summary>
/// Gets the virtual machine's configuration settings object.
/// </summary>
/// <param name="virtualMachine">The virtual machine.</param>
/// <returns>The virtual machine's configuration object.</returns>
public static ManagementObject
GetVirtualMachineSettings(
ManagementObject virtualMachine)
{
using (ManagementObjectCollection settingsCollection =
virtualMachine.GetRelated("Msvm_VirtualSystemSettingData", "Msvm_SettingsDefineState",
null, null, null, null, false, null))
{
ManagementObject virtualMachineSettings =
GetFirstObjectFromCollection(settingsCollection);
return virtualMachineSettings;
}
}
/// <summary>
/// Gets the Msvm_ComputerSystem instance that matches the host computer system.
/// </summary>
/// <param name="scope">The ManagementScope to use to connect to WMI.</param>
/// <returns>The Msvm_ComputerSystem instance for the host computer system.</returns>
public static ManagementObject
GetHostComputerSystem(
ManagementScope scope)
{
//
// The host computer system uses the same WMI class (Msvm_ComputerSystem) as the
// virtual machines, so we can simply reuse the GetVirtualMachine with the name
// of the host computer system.
//
return GetVirtualMachine(Environment.MachineName, scope);
}
/// <summary>
/// Gets the CIM_ResourcePool derived instance matching the specified type, subtype and
/// pool id.
/// </summary>
/// <param name="resourceType">The resource type of the resource pool.</param>
/// <param name="resourceSubtype">The resource subtype of the resource pool.</param>
/// <param name="poolId">The pool id of the resource pool.</param>
/// <param name="scope">The ManagementScope to use to connect to WMI.</param>
/// <returns>The CIM_ResourcePool derived instance.</returns>
public static ManagementObject
GetResourcePool(
string resourceType,
string resourceSubtype,
string poolId,
ManagementScope scope)
{
string poolQueryWql;
if (resourceType == "1") // OtherResourceType
{
poolQueryWql = string.Format(CultureInfo.InvariantCulture,
"SELECT * FROM CIM_ResourcePool WHERE ResourceType=\"{0}\" AND " +
"OtherResourceType=\"{1}\" AND PoolId=\"{2}\"",
resourceType, resourceSubtype, poolId);
}
else
{
poolQueryWql = string.Format(CultureInfo.InvariantCulture,
"SELECT * FROM CIM_ResourcePool WHERE ResourceType=\"{0}\" AND " +
"ResourceSubType=\"{1}\" AND PoolId=\"{2}\"",
resourceType, resourceSubtype, poolId);
}
SelectQuery poolQuery = new SelectQuery(poolQueryWql);
using (ManagementObjectSearcher poolSearcher = new ManagementObjectSearcher(scope, poolQuery))
using (ManagementObjectCollection poolCollection = poolSearcher.Get())
{
//
// There will always only be one resource pool for a given type, subtype and pool id.
//
if (poolCollection.Count != 1)
{
throw new ManagementException(string.Format(CultureInfo.CurrentCulture,
"A single CIM_ResourcePool derived instance could not be found for " +
"ResourceType \"{0}\", ResourceSubtype \"{1}\" and PoolId \"{2}\"",
resourceType, resourceSubtype, poolId));
}
ManagementObject pool = GetFirstObjectFromCollection(poolCollection);
return pool;
}
}
/// <summary>
/// Gets the CIM_ResourcePool derived instances matching the specified type, and subtype.
/// </summary>
/// <param name="resourceType">The resource type of the resource pool.</param>
/// <param name="resourceSubtype">The resource subtype of the resource pool.</param>
/// <param name="scope">The ManagementScope to use to connect to WMI.</param>
/// <returns>The CIM_ResourcePool derived instance.</returns>
public static ManagementObjectCollection
GetResourcePools(
string resourceType,
string resourceSubtype,
ManagementScope scope)
{
string poolQueryWql;
if (resourceType == "1") // OtherResourceType
{
poolQueryWql = string.Format(CultureInfo.InvariantCulture,
"SELECT * FROM CIM_ResourcePool WHERE ResourceType=\"{0}\" AND " +
"OtherResourceType=\"{1}\"",
resourceType, resourceSubtype);
}
else
{
poolQueryWql = string.Format(CultureInfo.InvariantCulture,
"SELECT * FROM CIM_ResourcePool WHERE ResourceType=\"{0}\" AND " +
"ResourceSubType=\"{1}\"",
resourceType, resourceSubtype);
}
SelectQuery poolQuery = new SelectQuery(poolQueryWql);
using (ManagementObjectSearcher poolSearcher = new ManagementObjectSearcher(scope, poolQuery))
{
return poolSearcher.Get();
}
}
/// <summary>
/// Gets the array of Msvm_StorageAllocationSettingData of VHDs associated with the virtual machine.
/// </summary>
/// <param name="virtualMachine">The virtual machine object.</param>
/// <returns>Array of Msvm_StorageAllocationSettingData of VHDs associated with the virtual machine.</returns>
public static
ManagementObject[]
GetVhdSettings(
ManagementObject virtualMachine)
{
// Get the virtual machine settings (Msvm_VirtualSystemSettingData object).
using (ManagementObject vssd = WmiUtilities.GetVirtualMachineSettings(virtualMachine))
{
return GetVhdSettingsFromVirtualMachineSettings(vssd);
}
}
/// <summary>
/// Gets the array of Msvm_StorageAllocationSettingData of VHDs associated with the given virtual
/// machine settings.
/// </summary>
/// <param name="virtualMachineSettings">A ManagementObject representing the settings of a virtual
/// machine or snapshot.</param>
/// <returns>Array of Msvm_StorageAllocationSettingData of VHDs associated with the given settings.</returns>
public static
ManagementObject[]
GetVhdSettingsFromVirtualMachineSettings(
ManagementObject virtualMachineSettings)
{
const UInt16 SASDResourceTypeLogicalDisk = 31;
List<ManagementObject> sasdList = new List<ManagementObject>();
//
// Get all the SASDs (Msvm_StorageAllocationSettingData)
// and look for VHDs.
//
using (ManagementObjectCollection sasdCollection =
virtualMachineSettings.GetRelated("Msvm_StorageAllocationSettingData",
"Msvm_VirtualSystemSettingDataComponent",
null, null, null, null, false, null))
{
foreach (ManagementObject sasd in sasdCollection)
{
if ((UInt16)sasd["ResourceType"] == SASDResourceTypeLogicalDisk)
{
sasdList.Add(sasd);
}
else
{
sasd.Dispose();
}
}
}
if (sasdList.Count == 0)
{
return null;
}
else
{
return sasdList.ToArray();
}
}
/// <summary>
/// Gets the virtual system management service.
/// </summary>
/// <param name="scope">The scope to use when connecting to WMI.</param>
/// <returns>The virtual system management service.</returns>
public static ManagementObject
GetVirtualMachineManagementService(
ManagementScope scope)
{
using (ManagementClass managementServiceClass =
new ManagementClass("Msvm_VirtualSystemManagementService"))
{
managementServiceClass.Scope = scope;
ManagementObject managementService =
GetFirstObjectFromCollection(managementServiceClass.GetInstances());
return managementService;
}
}
/// <summary>
/// Gets the virtual system management service setting data.
/// </summary>
/// <param name="scope">The scope to use when connecting to WMI.</param>
/// <returns>The virtual system management service settings.</returns>
public static ManagementObject
GetVirtualMachineManagementServiceSettings(
ManagementScope scope)
{
using (ManagementClass serviceSettingsClass =
new ManagementClass("Msvm_VirtualSystemManagementServiceSettingData"))
{
serviceSettingsClass.Scope = scope;
ManagementObject serviceSettings =
GetFirstObjectFromCollection(serviceSettingsClass.GetInstances());
return serviceSettings;
}
}
/// <summary>
/// Gets the virtual system snapshot service.
/// </summary>
/// <param name="scope">The scope to use when connecting to WMI.</param>
/// <returns>The virtual system snapshot service.</returns>
public static ManagementObject
GetVirtualMachineSnapshotService(
ManagementScope scope)
{
using (ManagementClass snapshotServiceClass =
new ManagementClass("Msvm_VirtualSystemSnapshotService"))
{
snapshotServiceClass.Scope = scope;
ManagementObject snapshotService =
GetFirstObjectFromCollection(snapshotServiceClass.GetInstances());
return snapshotService;
}
}
/// <summary>
/// Gets the first object in a collection of ManagementObject instances.
/// </summary>
/// <param name="collection">The collection of ManagementObject instances.</param>
/// <returns>The first object in the collection</returns>
public static ManagementObject
GetFirstObjectFromCollection(
ManagementObjectCollection collection)
{
if (collection.Count == 0)
{
throw new ArgumentException("The collection contains no objects", "collection");
}
foreach (ManagementObject managementObject in collection)
{
return managementObject;
}
return null;
}
/// <summary>
/// Takes a WMI object path and escapes it so that it can be used inside a WQL query WHERE
/// clause. This effectively means replacing '\' and '"' characters so they are treated
/// like any other characters.
/// </summary>
/// <param name="objectPath">The object management path.</param>
/// <returns>The escaped object management path.</returns>
public static string
EscapeObjectPath(
string objectPath)
{
string escapedObjectPath = objectPath.Replace("\\", "\\\\");
escapedObjectPath = escapedObjectPath.Replace("\"", "\\\"");
return escapedObjectPath;
}
/// <summary>
/// Verifies whether a job is completed.
/// </summary>
/// <param name="jobStateObj">An object that represents the JobState of the job.</param>
/// <returns>True if the job is completed, False otherwise.</returns>
private static bool
IsJobComplete(
object jobStateObj)
{
JobState jobState = (JobState)((ushort)jobStateObj);
return (jobState == JobState.Completed) ||
(jobState == JobState.CompletedWithWarnings) ||(jobState == JobState.Terminated) ||
(jobState == JobState.Exception) || (jobState == JobState.Killed);
}
/// <summary>
/// Verifies whether a job succeeded.
/// </summary>
/// <param name="jobStateObj">An object representing the JobState of the job.</param>
/// <returns><c>true</c>if the job succeeded; otherwise, <c>false</c>.</returns>
private static bool
IsJobSuccessful(
object jobStateObj)
{
JobState jobState = (JobState)((ushort)jobStateObj);
return (jobState == JobState.Completed) || (jobState == JobState.CompletedWithWarnings);
}
}
}