原网页地址:http://www.codeproject.com/KB/server-management/Intro2WMI2.aspx
Msvm_ComputerSystem
是我们需要掌握的第一个类,这个类代表主机或者虚拟机系统。下面显示了这个类的属性以及方法RequestStateChange 这个方法对管理vm的多种状态非常有用。下面是这个类的定义,它与传统的类的定义方式不同, 因为它采用的是MOF(Managed Object Format).
[Dynamic,
Provider
("VmmsWmiInstanceAndMethodProvider")]class Msvm_ComputerSystem : CIM_ComputerSystem
{
string Caption;
string Description;
string ElementName;
datetime InstallDate;
uint16 OperationalStatus[];
string StatusDescriptions[];
string Status;
uint16 HealthState = 5;
uint16 EnabledState;
string OtherEnabledState;
uint16 RequestedState;
uint16 EnabledDefault = 2;
datetime TimeOfLastStateChange;
string CreationClassName;
string Name = "GUID";
string PrimaryOwnerName;
string PrimaryOwnerContact;
string Roles[];
string NameFormat;
string OtherIdentifyingInfo[];
string IdentifyingDescriptions[];
uint16 Dedicated[];
string OtherDedicatedDescriptions[];
uint16 ResetCapability = 1;
uint16 PowerManagementCapabilities[];
uint64 OnTimeInMilliseconds;
datetime TimeOfLastConfigurationChange;
uint32 ProcessID;
uint16 AssignedNumaNodeList[];
};
现在,让我们获取一个Msvm_ComputerSystem类的对象,以便于我们能够执行方法RequestStateChange去改变vm的状态。首先让我们来定义一个 帮助程序,这个帮助程序会查询包含这个类的所有的属性和方法的命名空间,这个程序最终会返回一个ManagementObject对象,这个对象可以用来执行改变vm状态的方法。下面是Utility sample里的代码(默认之前已经定义了ManagementScope,此处省去了):
public static ManagementObject GetTargetComputer
(string vmElementName, ManagementScope scope)
{
string query = string.Format("select * from
Msvm_ComputerSystem Where ElementName = '{0}'", vmElementName);
ManagementObjectSearcher searcher = new
ManagementObjectSearcher(scope, new ObjectQuery(query));
ManagementObjectCollection computers = searcher.Get();
ManagementObject computer = null;
foreach (ManagementObject instance in computers)
{
computer = instance;
break;
}
return computer;
}
根据上面的方法,我们可以在程序里编写如下代码调用上面的方法获取Msvm_ComputerSystem 的一个实例:
ManagementObject vm = Utility.GetTargetComputer(vmName, scope);
vm就是我们获取到的Msvm_ComputerSystem实例,然后我们可以调用Msvm_ComputerSystem里的方法“RequestStateChange”,调用WMI类的方法需要用到GetMethodParameters,规则如下:
ManagementBaseObject inParams = vm.GetMethodParameters("RequestStateChange");
输入该方法需要的参数
inParams["RequestedState"] = Enabled;
ManagementBaseObject outParams =
vm.InvokeMethod("RequestStateChange", inParams, null);
if ((UInt32)outParams["ReturnValue"] == ReturnCode.Completed)
{
Console.WriteLine("{0} state was
changed successfully.", vmName);
}
else
{
Console.WriteLine("Change virtual system
state failed with error{0}", outParams["ReturnValue"]);
}
}
至此我们已经成功改变了vm的状态,但是有一些问题需要注意,上面的例子里将vm的状态改为Enalbled,但是在这之前并没有检查当前vm是否就是这个状态。要在修改状态前检查vm状态,我们可以参考之前写的一边文章。
除此之外,我们还注意到InvokeMethod不能立即返回成功与否的状态。当vm正在启动的时候(starting),它不能返回已启动状态(started),所以我们应该做个方法等待状态修改完成并报告这个最终执行情况。我们在Utility里定义了一个JobCompleted()方法,来跟踪InvokeMethod方法。
if ((UInt32)outParams["ReturnValue"]
== ReturnCode.Started)
{
if (Utility.JobCompleted(outParams, scope))
{
Console.WriteLine("{0} state was changed
successfully.", vmName);
}
else
{
Console.WriteLine("Failed to change
virtual system state");
}
}
else if ((UInt32)outParams["ReturnValue"]
== ReturnCode.Completed)
{
Console.WriteLine("{0} state was
changed successfully.", vmName);
}
else
{
Console.WriteLine("Change virtual
system state failed with error {0}",
outParams ["ReturnValue"]);
}
JobCompleted方法描述如下:
//This code demonstrates how the VM state change can be tracked
public static bool JobCompleted(ManagementBaseObject outParams,
ManagementScope scope)
{
bool jobCompleted = true;
//Retrieve msvc_StorageJob path. This is a full wmi path
string JobPath = (string)outParams["Job"];
ManagementObject Job = new ManagementObject(scope,
new ManagementPath(JobPath), null);
//Try to get storage job information
Job.Get();
while ((UInt16)Job["JobState"] == JobState.Starting
|| (UInt16)Job["JobState"] == JobState.Running)
{
Console.WriteLine("In progress... {0}% completed.",
Job["PercentComplete"]);
System.Threading.Thread.Sleep(1000);
Job.Get();
}
//Figure out if job failed
UInt16 jobState = (UInt16)Job["JobState"];
if (jobState != JobState.Completed)
{
UInt16 jobErrorCode = (UInt16)Job["ErrorCode"];
Console.WriteLine("Error Code:{0}", jobErrorCode);
Console.WriteLine("ErrorDescription: {0}",
(string)Job["ErrorDescription"]);
jobCompleted = false;
}
return jobCompleted;
}