Article Options
Premium Sponsor
Premium Sponsor

 »  Home  »  .NET Framework  »  WMI connections made easy in VB.NET  »  WMI Queries
WMI connections made easy in VB.NET
by Martin de Klerk | Published  04/24/2005 | .NET Framework | Rating:
WMI Queries

A note on WMI queries: the WMI Query Language (WQL) is modelled after SQL, and as such supports extending clauses like WHERE, WITHIN, HAVING etc. For instance, to retrieve the WMI representation of a selected printer on a remote computer, you could issue a query like "Select * From Win32_Printer Where Name=""hpdeskjet""". Executing this query should result in an ManagementObjectCollection containing a single ManagementObject representing the selected printer.

Enter O.S. dependency. When running Windows 9.x or ME, the extended WQL clauses like WHERE are not supported. In this case the only option is to retrieve all printer objects and select the correct WMI object by code:

    WmiQueryResult = myConn.ExecWmiQuery("Select * From Win32_Printer")
    For Each WmiObject In WmiQueryResult
        If WmiObject.GetPropertyValue("Name") = "hpdeskjet" Then
        End If

Yet More Pitfalls

I had to work my way through the WMI information-jungle with a machete. For every working VBScript/WBEM/C++ solution found on the internet, my determination to solve the problem on hand in VB.NET grew. During this ordeal I found many promising (WMI) pathways towards my goals, but in many cases I had to abandon that trail half-way due to O.S. dependencies having only a XP Pro client at my disposal.

Another point is managed vs. unmanaged code. In above sample the WmiObject is of type Win32_Printer. This WMI object gets it's properties derived from various WMI subsystems, like it shows in MSDN's definition of the Win32_Printer.Caption property:

    Data type: string
    Access type: Read-only
    Qualifiers: MaxLen(64)

Short description of an object, a one-line string. This property is inherited from CIM_ManagedSystemElement.

I discovered that many WMI properties were not available, as those were unmanaged code/data . Although disappointing, in .NET that makes sense. But it also restricted me by default to the use only those properties that were either WMI intrinsic, generic to the handled WMI object (no inheritance) or properties that were inherited from the CIM_ManagedSystemElement class.

For accessing unmanaged WMI code or data, check out the links provided at the end of this article.

An Added Bonus (or Two)

So why call the method .Poll() and not .Connect() ?
There are several reasons for this.

The first one being that the necessity for this class originated out of creating a network printer monitor program. The program had to be able to detect when a remote computer came on-line, and if so, automatically create the WMI connection to start querying the remote printers.

The second reason was that the ConnectionTester class was original intended to speed up the connection process. If a remote computer was not on-line, there was no reason to initiate a WMI connection which would take a considerable amount of time before throwing an exception. For the same reason the WMI availability check was to be performed only on the first time the remote was detected on-line.

The third reason is OS dependency. As certain WMI features and classes are only available under specific Windows versions, I needed an easy way to identify the version of Windows running on the remote computer. This is done by the Sub GetRemoteOsInfo() which is ( oh sweet irony!) totally OS dependent. Just check out the source code and you'll see what I mean.

The way the code is set up, you can use the ConnectionTester class for a more general use:

Bonus #1: You can switch off the WMI functionality of the ConnectionTester class, so it will perform only a quick online test. This, together with the addition of a Timer, enables you to build a simple connection monitor program. Just set .WmiCheck to False, load .ServerName with "", and in the Timer.Tick event ( or Timer.Elapsed event, depending on which Timer class you're using) simply place the following statements:

    If Not WmiConn.IsOnline Then
        Console.WriteLine("VBCity unavailable. " _
          & "Please switch to PANIC MODE and dial 911.")
    End If

Now, of course the VBCity server is not WMI enabled. But if it were the case, you should have no problem with retrieving WMI information over the Internet using the ConnectionTester class. That makes Bonus #2: Whether you need to manage WMI objects locally, on a computer in a LAN or a computer somewhere in this world connected to the Internet, it is completely transparent using the ConnectionTester class.

Sponsored Links