2

TL/DR:

The main issue is this: I get a ManagementBaseObject as returned value. But I cannot call its methods, as it doesn't have the InvokeMethod() member, like ManagementObject has. So how do I call its member-methods?

elaboration:

I open a BcdStore object:

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);

But this object is useless:

// 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!
Community
  • 1
  • 1
Tar
  • 8,529
  • 9
  • 56
  • 127
  • This question may be of help, depending on what you are ultimately trying to do: http://stackoverflow.com/questions/9337354/access-the-windows-7-boot-configuration-data-using-c-sharp – Paul Griffin Mar 24 '15 at 14:52
  • @PaulGriffin, I can accomplish the strategic goal here via this or that method (this is what I actually do), but I really want to understand the logic here: this situation is odd, I get a returned object with which I'm supposed to be able to do stuff, but I can't find how it's being done... – Tar Mar 25 '15 at 08:12

1 Answers1

2

Probably it's a bug, because PropertyData always returns ManagementBaseObject if Type's value is CimType.Object (source). The return value of InvokeMethod is also ManagementBaseObject(source), except when ManagementOperationObserver is used.

Example without an observer:

// result is ManagementBaseObject
// result["__GENUS"] == 2
var result = bcdCls.InvokeMethod("OpenStore", methodParams, null);

Example with an observer:

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
}

In the second snippet we have a ManagementObject, because the ManagementBaseObject.GetBaseObject method is used internally (source). So you can report to Microsoft.

And finally, workaround:

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
}
Yoh Deadfall
  • 2,711
  • 7
  • 28
  • 32
  • In the example with the `ManagementOperationObserver`, how do I get the `BcdStore` as `ManagementObject` ? it doesn't matter whether `results = bcd.InvokeMethod(...,"OpenStore",...)` returns `ManagementBaseObject` or `ManagementObject`, what I need to be `ManagementObject` is what `results["store"]` returns. This assertion fails: `Assert.IsInstanceOfType(bcd.InvokeMethod(...,"OpenStore",...)["store"], typeof(ManagementObject));` – Tar Mar 26 '15 at 15:15
  • 1
    Nohow, because `results["store"]` is getting value of the property which returns only `ManagementBaseObject`'s. You can use either reflection to get a `ManagementObject` or [query it](http://stackoverflow.com/questions/28967075/why-new-managementobjectroot-wmi-bcdstore-null-throws-exception). Also you can use my answer to report the strange behavior/bug of the `InvokeMethod to Microsoft. – Yoh Deadfall Mar 26 '15 at 16:28
  • 1
    [Feedback](https://connect.microsoft.com/VisualStudio/feedback/details/1209371/the-propertydata-value-getter-returns-a-managementbaseobject-instead-a-managementobject) on Microsoft Connect. – Yoh Deadfall Mar 28 '15 at 09:57
  • This is an elite answer - that's sure, but I accept it for now with mixed feelings, as it relies on reflection and private fields names. Who knows when it's going to break? it seems very odd to me that `Microsoft` "managed to keep" this major "bug" unnoticed - which leads me to suspect it's not a bug, that it is the wrong way of doing it... – Tar Mar 29 '15 at 14:57