How to list the members of a WMI OLEObject

I was inspecting some hardware properties and wrote the following

//  Connect to WMI
Var locator As OLEObject = New OLEObject("WbemScripting.SWbemlocator", True)

Var wmiServiceParams() As Variant

// Set the WMI local params
wmiServiceParams.Add Nil // Param 0 is ignored
wmiServiceParams.Add "."
wmiServiceParams.Add "root\cimv2"

Var computerBoard As OLEObject = OLEObject(locator.Invoke("ConnectServer", wmiServiceParams)).InstancesOf("Win32_baseboard").ItemIndex(0)

MessageBox  "Manufacturer: "+computerBoard.Manufacturer
MessageBox "Model: "+computerBoard.Model // This line raises a null access at my Dell, the work around is computerBoard.Value("Model")

computerBoard = Nil
locator = Nil

Exception err 
MessageBox  err.message

As you see, besides MS docs saying that “Model” should exist, seems that sometimes it may not.

I’m curious to list true ones.

So the question is, how do I, possessing the computerBoard OLEObject above, can build an Enumerator from it, and list its member names in Xojo?

1 Like

Oh boy I remember years ago stumbling onto how to do this and was told by Aaron Baldwin at the time that it was not possible

This was some years ago and sorry my memory is fuzzy at the moment

Well I just read the news that WMIC is deprecated so I’m very interested in how to get this information without shell.

1 Like

@Tim_Parnell
Yes WMIC is no longer supported in Windows OS going forward

But connecting to Cimv2 is not deprecated

1 Like

We Need a hand of @William_Yu here because I can’t advance after this point:

Error, line 16
There is more than one method with this name but this does not match any of the available signatures.


//  Connect to WMI
Var locator As OLEObject = New OLEObject("WbemScripting.SWbemlocator", True)

Var wmiServiceParams() As Variant

// Set the WMI local params
wmiServiceParams.Add Nil // Param 0 is ignored
wmiServiceParams.Add "."
wmiServiceParams.Add "root\cimv2"

Var computerBoard As OLEObject = OLEObject(locator.Invoke("ConnectServer", wmiServiceParams)).InstancesOf("Win32_baseboard").ItemIndex(0)

Var props As OLEObject = computerBoard.SystemProperties__  // ISWbemPropertySet

Var propEnumerator As New COM.IEnumVariant(props._NewEnum) // Something wrong here, what?

Var prop As Variant
var fetched As UInt32

Call propEnumerator.Next_(1, prop,  fetched ) // read one property for test


Break // Want to observe the property returned


propEnumerator = nil
props = nil
computerBoard = Nil
locator = Nil

exception err 
msgbox err.message

Ok, MS Docs says that SWbemPropertySet._NewEnum returns an IEnumVariant, so an explicit cast “fix” the Xojo conflict but… I get a NULL instead of an Enumerator.

Var propEnumerator As New COM.IEnumVariant(COM.IEnumVariant(props._NewEnum)) // NOE!?

The properties are there, as we can see that props.Count returns a number

Xojo bug? Something else?

Just for information, the computerBoard.SystemProperties_ is stated in MS Docs as using ONE UNDERLINE but to make it work in Xojo I had to add TWO UNDERLINES .SystemProperties__ , because I saw Xojo “eating” one of the underlines in the debug.

Ok, I’ve made it work for my intents using another approach.

It’s just a proof of concept, probably needs enhancements when adapting for general use.

// This is just a proof of concept about reading WMI data
// Use it just as an example to you understand the concept and build something best suited for a proper use

//  Connect to WMI
Var locator As OLEObject = New OLEObject("WbemScripting.SWbemlocator", True)

Var wmiServiceParams() As Variant

// Set the WMI local params
wmiServiceParams.Add Nil // Param 0 is ignored
wmiServiceParams.Add "."
wmiServiceParams.Add "root\cimv2"

Var computerBoard As OLEObject = OLEObject(locator.Invoke("ConnectServer", wmiServiceParams)).InstancesOf("Win32_baseboard").ItemIndex(0)

Var xmlString As String = computerBoard.GetText__(1) // Here we get all the properties data as XML
Var xmlComputerBoard As New XmlDocument(xmlString)
Var xmlWalker As XmlNode

Var data As New Dictionary // the data Dictionary will receive all the properties

// Let's build the dictionary from that WMI XML

xmlWalker = xmlComputerBoard.DocumentElement.FirstChild

Do Until xmlWalker = Nil
  
  Var nameProperty As String = xmlWalker.GetAttribute("NAME")
  
  Var valuesFound As Variant = Nil
  
  If xmlWalker.ChildCount >= 1 Then
    
    If xmlWalker.FirstChild.Name = "VALUE" Then
      
      valuesFound = xmlWalker.FirstChild.FirstChild.Value
      
    ElseIf xmlWalker.FirstChild.Name = "VALUE.ARRAY" Then
      
      Var list() As Variant 
      
      Var xmlValue As XmlNode = xmlWalker.FirstChild.FirstChild
      
      Do Until xmlValue = Nil
        
        list.Add xmlValue.FirstChild.Value
        xmlValue = xmlValue.NextSibling
        
      Loop
      
      valuesFound = list
      
    End
  End
  
  data.Value(nameProperty) = valuesFound
  
  xmlWalker = xmlWalker.NextSibling
  
Loop

Break // data dictionary contains all the data at this point 

3 Likes