Advertisment

Questionable Management

author-image
PCQ Bureau
New Update

In the last two parts of the series we saw how and why WMI exists. We even saw a small bit of code in WMI and how easy it was to write it using class abstractions provided by WMI. In this concluding part of the series, we look at an interesting way to derive and manipulate WBEM data. Let's dive in.

Advertisment

WMI Query Language 


This has a shorter acronym-WQL-and is not much different from your standard SQL commands. Only, instead of tables, we use WMI classes. Instead of column names, we use properties of these classes. For example, in the previous part we wrote a 'For loop' to retrieve the Win XP product ID from WMI. The code was something like this.

For Each Obj In oWPA

If (Mid(Obj.ProductID, 7, 10) = seqNumber) Then

...

End If

Next

Advertisment
Direct Hit!
Applies to: Intermediate/advanced Windows programmers
USP: Use WQL to retrieve and manage WMI data through your applications

The same code can be condensed if we use WQL to get the information, thus,

"SELECT * FROM Win32_WindowsProductActivation WHERE (SUBSTRING(ProductID, 7, 10)='" + seqNumber + "');"

Advertisment

How to use ?


In order to use WQL, the base WMI object, which we still retrieve using the GetObject function, exposes the ExecQuery method. This method takes the WQL statement as a single string parameter. ExecQuery returns objects by default and the exact type will depend on what we queried for. We can ask for data (like we did in the above example), for event information from the Windows Event Log, or we can request schema (class definition) information. In order to fully support WMI, WQL has extended the SQL by adding new operators and clauses. For example, we can use the following WQL to get only those classes that derive from the Win32_LogicalDisk class.

Obj = GetObject("winmgmts:").ExecQuery("SELECT * FROM meta_class WHERE __this ISA 'Win32_LogicalDisk'")

In the above statement, 'meta_class' and '__this' are the intrinsic WMI class and property, respectively. The ISA operator checks for the type of class. In place of '__this', we can use a property that will return a class-object. The other parameter for ISA is obviously the super class, which the object in '__this' is derived from. 

Advertisment

Powerful queries


We can use the ASSOCIATORS OF statement to retrieve all objects associated with a particular instance of another object. This is a full and new statement in WQL that does not use SELECT or other usual words at the beginning of the statement. 

We cannot use WHERE modifiers like OR and AND to limit results. Also, we must use the equality only (not inequality or lesser/greater than) when using the ASSOCIATORS OF. A typical example would be:

ASSOCIATORS OF (Win32_LogicalDisk.DeviceID="C:") WHERE
ResultClass=CIM_Directory

Advertisment

to get all the directories under the C drive of the system. The ResultClass parameter above the filter results to include only those elements that are of type CIM_Directory. Additional parameters such as the role of the object (Role), role of the result (ResultRole), some qualifier (RequiredQualifier, RequiredAssocQualifier) and the class that links the two together (AssocClass) can be added in the WHERE clause.

Event queries


For event notifications, the SELECT statement adds a new clause in the form of WITHIN. We can add the GROUP keyword in this clause to group the results. As such, the WITHIN clause allows us to specify polling intervals for WMI events. The GROUP keyword will cause the WMI system to send all events generated at that instant to be grouped and sent to us in one batch instead of as separate notifications. 

Obviously, we will use a return class of the appropriate event-notification type on the other side of the statement.

Advertisment

Obj = GetObject("winmgmts:").ExecQuery("SELECT * FROM __InstanceModificationEvent WITHIN 10 WHERE TargetInstance ISA 'Win32_LogicalDisk'")

The above statement returns disk change notifications every 10 seconds. If we had said 'GROUP WITHIN 10' here, we would get all disk change events (every 10 seconds) in one batch.

Depending on the particular event, WMI classes may share data and the task of providing events. It will be useful to study associated and sister classes of the ones we are receiving events from, and checking to see what other data we can get. 

Advertisment

For example, if there is a 'Create' class for something, there usually will also exist the 'Modify' and the 'Delete' sister classes. While Create and Modify will share data, Delete will not-since they would have different ways of working.

Log files


WMI creates many log files to monitor events of all types. A complete list of these files and what they are meant for is available at
http://msdn.microsoft.com/library/en-us/wmisdkwmi/wmi_log_files.asp.
We can also change WMI logging behavior by modifying a few registry keys as described in another document at
http://msdn.microsoft.com/library/en-us/wmisdk/wmi/logging_wmi_activity.asp.
Studying these log files helps to both narrow down on system-related problems as well as fine-tune our applications.

Things you cannot do with WQL


WQL queries can't return an array data type. If you need to access or modify such information, you will need to use regular looping constructs to iteratively process them. An eg of such a scenario would be requesting IP addresses assigned to a particular network adapter. All forms of this query, whether API or WMI, would return an array. The number of operators like AND and OR that you can use in a WQL query are also limited. Its exact number would depend on the complexity of the particular query. Use as few of these operators as possible. If they be too many, then consider first getting a more general subset of rows and then iterate through them using a loop construct. When the number of used operators is too large, you would get a WBEM_E_QUOTA_VIOLATION error. WQL will also not allow you to query across WMI namespaces. If you want to figure out all the instances of a particular WBEM class, then you will need to find a way other than using WQL for it.

Further steps


For the not-so-faint-of-heart, we can write our own providers to interact with WMI. This gives us a powerful and extensible platform for building robust, scalable and reliable back-end systems. WMI can also be harnessed to provide infrastructural management services for roaming networks (WiFi), through bindings of SENS and native Windows wireless services. Using SENS here cuts down on polling times and unreliability, while maintaining a disconnected architecture. Lastly, WMI providers can be accessed in .NET through System.DirectoryServices, this makes leveraging WMI for enterprise applications easy.

Sujay V Sarma

Advertisment

Stay connected with us through our social media channels for the latest updates and news!

Follow us: