Search code examples
c#.netvb.netwindowswmi

Perform a single WMI query to multiple classes, it is possibly?


I need to perform various queries to different WMI classes, then instead of doing query one by one, to improve the speed of execution I thinked in this:

In C# or else VB.Net, I would like to know whether a single query can be done to retrieve the properties of multiple classes at once.

Random not functional example:

Using wmi As New Management.ManagementObjectSearcher(
    "select SerialNumber from Win32_BaseBoard, select Caption from Win32_Process"
)

...

End Using

If yes, which is the proper query syntax?


Solution

  • How about this, using NET 4.5:

    Imports System.Management
    Imports System.Collections.Concurrent
    Imports System.Threading.Tasks
    
    Dim wql As String() = {"SELECT SerialNumber FROM Win32_BaseBoard",
                                   "SELECT Name FROM Win32_BIOS",
                                   "SELECT VideoProcessor FROM Win32_VideoController",
                                   "SELECT RegisteredUser FROM Win32_OperatingSystem"}
    
    Dim tasks As New List(Of Task)
    For Each q In wql
        Dim t As task = Task.Run(Sub()
                                     Dim str = WMI.GetWMIClassProperty(q)
                                     wList.Add(str)
                                 End Sub
        )
        tasks.Add(t)
    Next
    
    Task.WaitAll(tasks.ToArray)
    

    This is the NET 4.0 version:

    Dim wmiAction As Action(Of Object) = Sub(s As Object)
                                             Dim str = WMI.GetWMIClassProperty(s.ToString)
                                             wList.Add(str)
                                         End Sub
    
    Dim tasks As New List(Of Task)
    For Each q In wql
        Dim t As New task(wmiAction, q)
        tasks.Add(t)
        t.Start()
    Next
    
    Task.WaitAll(tasks.ToArray)
    

    WMI.GetWMIClassProperty just creates a searcher for the query and returns the first property or String.Empty.

    Using a Stopwatch it takes 72-80ms to run the 4 in succession, 15-20ms to run them as Tasks (NET 4 ver is 2-3ms slower). Almost as fast (18-25ms) is a Parrallel.ForEach but seems a but less involved and also works with NET 4.0:

    Parallel.ForEach(wql, Sub(thisQ)
                              Dim str = WMI.GetWMIClassProperty(thisQ)
                              wList.Add(str)
                          End Sub)
    

    All four methods return the same results in wList, though in differing orders, so you'd want a way to qualify which results are which. The differences do increase if you query some of the truly slow WMI classes.