如何调用 ManagementBaseObject 方法或获取 ManagementObject?
How to call ManagementBaseObject methods or get a ManagementObject?
TL/DR:
主要问题是:我得到一个 ManagementBaseObject
作为返回值。但是我不能调用它的方法,因为它没有 InvokeMethod()
成员,而 ManagementObject
有。那么如何调用它的成员方法呢?
阐述:
我打开一个BcdStore
对象:
var bcdCls = new ManagementClass(@"root\WMI", "BcdStore", null); // OpenStore is a static method
var methodParams = bcdCls.GetMethodParameters("OpenStore");
methodParams["file"] = ""; // the default store
var results = bcdCls.InvokeMethod("OpenStore", methodParams, null);
Assert.IsNotNull(results);
var store = results["store"] as ManagementBaseObject;
Assert.IsNotNull(store);
但是这个对象没用:
// unfortunately, it is not a ManagementObject, so no InvokeMethod() is possible :-(
Assert.IsNull(store as ManagementObject);
store.InvokeMethod("EnumerateObjects", new object[] { 0 }); // Compilation error!
// ManagementBaseObject doesn't have an InvokeMethod member method!
可能是一个错误,因为如果 Type
的值是 CimType.Object
(source). The return value of InvokeMethod
is also ManagementBaseObject
(source),PropertyData
总是 returns ManagementBaseObject
,除非使用 ManagementOperationObserver
。
没有观察者的例子:
// result is ManagementBaseObject
// result["__GENUS"] == 2
var result = bcdCls.InvokeMethod("OpenStore", methodParams, null);
观察者示例:
var observer = new ManagementOperationObserver();
observer.ObjectReady += ObjectReady;
bcd.InvokeMethod(observer, "OpenStore", methodParams, null);
void ObjectReady(object sender, ObjectReadyEventArgs e)
{
// e.NewObject is ManagementObject
// e.NewObject["__GENUS"] == 2
}
在第二个片段中我们有一个 ManagementObject
,因为 ManagementBaseObject.GetBaseObject
方法在内部使用 (source)。所以你可以向微软报告。
最后,解决方法:
var bcd = new ManagementClass(@"root\WMI", "BcdStore", null);
var openStoreParams = bcd.GetMethodParameters("OpenStore");
openStoreParams["File"] = "";
var openStoreResult = bcd.InvokeMethod("OpenStore", openStoreParams, null);
var openedStore = (ManagementObject)typeof(ManagementBaseObject)
.GetMethod("GetBaseObject", BindingFlags.Static | BindingFlags.NonPublic)
.Invoke(
null,
new object[]
{
typeof(ManagementBaseObject)
.GetField("_wbemObject", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(openStoreResult["Store"]),
bcd.Scope
}
);
var enumObjectsParams = openedStore.GetMethodParameters("EnumerateObjects");
enumObjectsParams["Type"] = 0;
var enumObjectsResult = openedStore.InvokeMethod("EnumerateObjects", enumObjectsParams, null);
var enumObjects = (ManagementBaseObject[])enumObjectsResult["Objects"];
foreach (var enumObject in enumObjects)
{
// Do something
}
TL/DR:
主要问题是:我得到一个 ManagementBaseObject
作为返回值。但是我不能调用它的方法,因为它没有 InvokeMethod()
成员,而 ManagementObject
有。那么如何调用它的成员方法呢?
阐述:
我打开一个BcdStore
对象:
var bcdCls = new ManagementClass(@"root\WMI", "BcdStore", null); // OpenStore is a static method
var methodParams = bcdCls.GetMethodParameters("OpenStore");
methodParams["file"] = ""; // the default store
var results = bcdCls.InvokeMethod("OpenStore", methodParams, null);
Assert.IsNotNull(results);
var store = results["store"] as ManagementBaseObject;
Assert.IsNotNull(store);
但是这个对象没用:
// unfortunately, it is not a ManagementObject, so no InvokeMethod() is possible :-(
Assert.IsNull(store as ManagementObject);
store.InvokeMethod("EnumerateObjects", new object[] { 0 }); // Compilation error!
// ManagementBaseObject doesn't have an InvokeMethod member method!
可能是一个错误,因为如果 Type
的值是 CimType.Object
(source). The return value of InvokeMethod
is also ManagementBaseObject
(source),PropertyData
总是 returns ManagementBaseObject
,除非使用 ManagementOperationObserver
。
没有观察者的例子:
// result is ManagementBaseObject
// result["__GENUS"] == 2
var result = bcdCls.InvokeMethod("OpenStore", methodParams, null);
观察者示例:
var observer = new ManagementOperationObserver();
observer.ObjectReady += ObjectReady;
bcd.InvokeMethod(observer, "OpenStore", methodParams, null);
void ObjectReady(object sender, ObjectReadyEventArgs e)
{
// e.NewObject is ManagementObject
// e.NewObject["__GENUS"] == 2
}
在第二个片段中我们有一个 ManagementObject
,因为 ManagementBaseObject.GetBaseObject
方法在内部使用 (source)。所以你可以向微软报告。
最后,解决方法:
var bcd = new ManagementClass(@"root\WMI", "BcdStore", null);
var openStoreParams = bcd.GetMethodParameters("OpenStore");
openStoreParams["File"] = "";
var openStoreResult = bcd.InvokeMethod("OpenStore", openStoreParams, null);
var openedStore = (ManagementObject)typeof(ManagementBaseObject)
.GetMethod("GetBaseObject", BindingFlags.Static | BindingFlags.NonPublic)
.Invoke(
null,
new object[]
{
typeof(ManagementBaseObject)
.GetField("_wbemObject", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(openStoreResult["Store"]),
bcd.Scope
}
);
var enumObjectsParams = openedStore.GetMethodParameters("EnumerateObjects");
enumObjectsParams["Type"] = 0;
var enumObjectsResult = openedStore.InvokeMethod("EnumerateObjects", enumObjectsParams, null);
var enumObjects = (ManagementBaseObject[])enumObjectsResult["Objects"];
foreach (var enumObject in enumObjects)
{
// Do something
}