Introduction to WQL: SQL for WMI

According to Microsoft’s MSDN, the WMI Query Language (WQL) is a subset of the American National Standards Institute Structured Query Language (ANSI SQL) with minor semantic changes. Queries built using WQL are used to control the WMI Service.

Those familiar with SQL will find making the adjustment to WQL very simple.  Those new to it will probably find it a bit tough to learn in the beginning.  Once you start getting a handle on the query logic and the command structure, it should become dramatically easier.

It’s important to have some understanding of how WMI works.  It’s also difficult to give a clear-cut definition. Try to think of WMI as a repository of properties and methods related to the system environment that you will access like a database.

While WMI’s intended purpose was to provide access to system hardware, it has since been expanded to cover network protocols, the Windows registry, and much more.  And it can be further expanded by adding additional Providers.

Providers are groups of WMI Classes that are designed to perform specific or similar tasks.  They consist of the necessary code (methods involved in retrieving and setting data) and a schema (a document describing the type of information being returned).

Think of Providers as individual databases within your WMI repository.  While you’ll learn an exclusion later (Associators), for the most part, you cannot move between Providers.  You must make a unique query for each one you need. (In WSH, this means instantiating separate objects for each of them).

Individual groups of related methods and properties are contained within WMI Classes. Think of Classes as the tables within your imaginary database. They contain groups of properties and methods that can be polled and manipulated like data fields.

The topics in this article are very broad. I don’t have any way to cover them thoroughly. My aim is to provide you with a starting place to work from. There have been a number of excellent books written on the subjects of WMI and SQL should you want more information.

There are three types of WQL queries supported by WMI.  We’re going to take a look at each of them now.  I’m also going to show you an example of each.  Don’t worry if you don’t fully understand the syntax.

{mospagebreak title=Data Queries}

Data Queries

These are the most common type of WMI query.  Data queries poll WMI for specific information by returning property values.  These are generally also the simplest type of queries.

strComputer = "."

Set objWMIService = GetObject("winmgmts:" & strComputer & "rootCIMV2")

Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_NTLogEvent" _

    & " WHERE Logfile = ‘Application’")

This is a relatively simple query.  We begin by connecting to WMI’s CIMV2 Providers.  Then, we make use of the WMIService’s ExecQuery method to issue the query whose results are returned as a collection of objects.  The query, which is passed as a string, looks like the following:

SELECT * FROM Win32_NTLogEvent WHERE Logfile = ‘Application’

We want to SELECT all (*) items from the Win32_NTLogEvent class WHERE the Logfile property is equal to “Application.”

All queries begin with the SELECT keyword.  The next piece of the query determines how much information is returned about each object.  The wildcard indicates that all available information should be returned.

Next is the FROM keyword.  This tells WMI which of the Provider’s classes should be polled.  In our example, the Win32NTLogEvent class houses all of the event log entries.

This example also makes use of a WHERE clause to further control what information is returned.  The query will only return items from our class whose Logfile property matches the string “Application.”  Notice that strings use single quotes, and that this is a strict match.  Items “containing” this string will not be returned.

To perform a partial match in WQL, make use of the LIKE keyword in place of the = operator.

A WHERE clause must be in the form of a conditional statement.  Only those items that evaluate to True will be returned.  Executing this query will return a collection of objects representing each entry in the Windows NT Application Event Log.

{mospagebreak title=Event Queries}

Event Queries

The second type of query is a little less common, but extremely powerful when used correctly. The Event query creates a temporary event request notification that is flagged each time a new instance of a class is created.

If we look at the last example, we were polling the Win32_NTLogEvent class for event log entries.  We can use an Event Query to watch that class for any newly created instances as well.

strComputer = "."

Set objWMIService = GetObject("winmgmts:" & strComputer & "rootcimv2")

Set colEvents = objWMIService.ExecNotificationQuery _

   ("SELECT * FROM __InstanceCreationEvent WHERE " _

       & "TargetInstance ISA ‘Win32_NTLogEvent’ " _

       & "AND TargetInstance.Logfile = ‘Application’ ")

The structure of this query is a little more complex, but it’s not difficult.  You’ll find that it’s very similar to the data query we used.

Again we’re going to SELECT all instances with our wildcard FROM the __InstanceCreationEvent event type.  We’re looking for the request notification returned by our event so the FROM keyword should point to the event, not the class in which the event occurs.

Then we set up a WHERE clause to filter our results.  This is where it looks a little funny.  Notice how we’re not calling the properties directly this time?  That’s because we can’t reference the class item directly.  We’re only returning event results.  So we use the TargetInstance moniker to refer to the returned event.

A moniker is like a pointer that cross references items in different classes.

The ISA is a keyword to refer to the referenced properties.  So our query is looking for all events WHERE the TargetInstance is a member of the Win32_NTLogEvent class AND the TargetInstance’s Logfile property is set to “Application.”

So this event query would return any newly created events that fit the description in our first example.  The data query returns any existing items when it is run and the event query returns any newly created items after it is run.

{mospagebreak title=Schema Queries}

Schema Queries

Okay.  We know how to build queries that return data information, and we know how to build queries that wait for new information.  What if we want to know what type of information is available?  Or more specifically, what type of information a specific class holds?

We can do this by checking the class’ schema.  As you recall, the schema defines the type of information contained in the class.  This third and final type of WMI query is the Schema Query.  Take a look at this example.

SELECT * FROM meta_class WHERE __this ISA "Win32_BaseService"

This query returns all information for elements in the Win32_BaseService class.  Building and using Schema queries is a bit beyond the scope of this article.

This is also, by far, the least used of all the query types.  In fact, most scripters will probably never have a real-world use for it.  A Google search should return some valuable results if you’re interested in learning more.

You may also want to check out the MSDN WQL Reference.  It’s a very good resource explaining the different keywords available as well as the query structure.

I hope I’ve given you a workable introduction to the WMI Query Language.  The only way to really learn WQL is to build a basic script and just start playing with it.  It will come to you with practice.

Learning to become proficient in WMI will take your scripting to a whole new level.  It’s much more powerful and comprehensive than WSH or VBS alone.  Good luck in your scripting endeavors.  Until next time…

One thought on “Introduction to WQL: SQL for WMI

  1. In order to harness the power of WMI in your scripts, you’ll need to be able to construct queries with WQL. Hopefully, this article will help get you started.

[gp-comments width="770" linklove="off" ]