WMI Programming with Visual Basic.NET: What is the WQL?
The goal of this series is to introduce Microsoft Windows Management Instrumentation (WMI) and get you up and running as quickly as possible, using it to manage your system through the WMI programming using .NET. This article covers querying WMI with the Windows Query Language.
You can download the zip of entire Visual Studio.NET solution (developed for this article) here.
The first part of this series covered the basics of WMI and how to access WMI information from Visual Basic.NET (both locally and remotely). In this article, I will introduce you to the concept of WQL together with types of WQL queries.
The first article in this series gave you the details for creating a Visual Studio.NET solution for WMI, from scratch. This information will not be repeated in any of the future articles in this series.
Querying WMI with WQL (local environment)
Anyone who works in the IT sector would definitely hear about SQL. Structured Query Language (SQL) is a great querying language for relational databases. As SQL is used for relational databases, WQL is used to query WMI information. But, one should consider that it is not as robust as SQL. In this article, I will cover only the basics of WQL rather than going into very great depth at this moment.
The WMI Query Language (WQL) is a subset of the American National Standards Institute Structured Query Language (ANSI SQL)—with minor semantic changes. We can just consider WQL as something like “WMI + SQL = WQL”.
The following is a small example which demonstrates a simple SELECT statement in WQL.
DimsearcherAsNewManagementObjectSearcher("SELECT * FROM Win32_LogicalDisk")
You can obtain the above code from “form1.vb” file in the zip file included for download. If you observe the above code and compare it with my previous examples (present in part one), there exists only a small difference, as follows:
DimsearcherAsNewManagementObjectSearcher("SELECT * FROM Win32_LogicalDisk")
In the first statement, I am using a new class named “ManagementObjectSearcher”, used to retrieve a collection of management objects based on a specified query. The class got a method “get()” to retrieve all instances of objects based on the query specified. And I hope the rest is the same.
The first article of the series introduced the concept of remote connectivity through WMI. If you really don’t have any idea about remote connectivity through WMI, I suggest you read it. The same concept is being implemented here, but with a mixture of WQL in between!
You can obtain the above code from the “form2.vb” file in the zip included for download. The above program is just the combination of the previous section and the last section from the first article. The only new issue is the following statement:
DimsearcherAsNewManagementObjectSearcher(scope,NewSelectQuery("SELECT * FROM Win32_LogicalDisk"))
In the previous section, we just issued the SELECT statement in the form of a string. But in the above statement, I created an object of class “SelectQuery” to pass the SELECT query. When scope is provided exclusively, the object of “SelectQuery” is necessary, as the “ManagementObjectSearcher” constructor is expecting an object of type “ObjectQuery”. In the previous section, the scope defaults to “root\cimv2” of the local server (or system). Apart from the above statement, the rest is the same.
Make sure that you change the “hostname” in the above program, according to your needs. Similarly, provide your own credentials of username and password to connect the host.
The previous sections just demonstrated some simple examples of WQL. Actually WQL has its own classification of queries. They are as follows:
Data Queries
Event Queries
Schema Queries
Every WMI class instance represents a physically existing resource residing at your computer or on the network or at any location. Any physical resource (or instance) would definitely fall into a category of a particular WMI class, where we can query all those instances through WQL.
Data queries are used to retrieve WMI class instances and data associations. They are the most commonly used type of query in WMI scripts and applications. All the examples in the previous sections are of the Data query type (as we are trying to retrieve the instances of WMI class ‘Win32_LogicalDisk’).
Every programmer knows that the entire Windows operating system is event-driven. Anything you operate with Windows OS is an event. Examples of events include logging in, logging out, printing a page, installing software, opening an application, connecting to a network, and so forth. Now, say I wanted to have some script executed when someone logs in. That means my script should register to the “login” (for example) event, and continuously listen for that event to occur. When the event occurs, my script gets executed.
These kinds of scripts (listening for events of WMI) are called consumers. Consumers use event queries to register and receive notification of events. Event providers use event queries to register one or more events. In general, the queries used for trapping event notifications are called “event queries” (which will be discussed in my upcoming articles).
How do you list all of the namespaces available? How many sub-namespaces does each of the main namespaces contain? What are the classes owned by a particular namespace? How do you get this type of information (programmatically)? For all of the previous questions, “schema queries” is the answer. Schema queries are used to retrieve class definitions (rather than class instances) and schema associations. Schema queries use the SELECT statement with syntax similar to that for data queries. The difference is the use of a special class called “meta_class”, which identifies the query as a schema query. Schema queries only support "*" in the SELECT statement. To narrow the scope of the definitions returned, a provider can add a WHERE clause that specifies a particular class.
The next section will give you some introduction to schema queries and how to use them efficiently to solve our needs.
As explained in the previous section, schema queries are used to retrieve class definitions. The following simple example lists all of the classes in the WMI environment.
DimsearcherAsNewManagementObjectSearcher("SELECT * FROM meta_class")
Interesting! You will be able to find approximately 800+ classes. So, you can imagine how much information you can gather from WMI. You can observe that the SELECT statement is being used with “meta_class” which works in a way similar to the concept of reflection in .NET. You can obtain the above code from the “form3.vb” file in the zip included for download.
Can we get all of the namespaces in the same way as above? Why not? I hope you would be glad to work with that one too. The following shows you how to do it (and can be found at “form4.vb”):
DimnsClassAsNewManagementClass( _
NewManagementScope("root"), _
NewManagementPath("__namespace"), _
Nothing)
DimnsAsManagementObject
ForEachnsInnsClass.GetInstances()
Me.lstMembers.Items.Add(ns("Name").ToString())
Next
Can we get all of the sub-namespaces of a particular namespace? Why not? In the above example, replace “root” with your own known namespace such as “root\cimv2” or “root\Microsoft” or whatever is appropriate. The program automatically retrieves all of the sub-namespaces available within the namespace specified (and can be found at “form5.vb”).
And finally, the following example gives you the list of all the classes available in a particular namespace (and can be found at “form6.vb”).
In the above program, you can replace “me.lstnamespaces.text” with any namespace you want. The above program actually tries to list all the classes of the namespace selected in the ‘lstNamespaces’ control.
Using all of the examples in this section, together with some investigation of System.Management classes, you can also design WMI object explorer (both for local and remote) completely by yourself. The object explorer could either be windows based or Web based (following the strategy of WBEM). But, it needs some indepth study of certain classes within the same namespace. I leave it to the readers to further investigate and research the System.Management namespace.
For a complete list of all namespaces and classes, I suggest you refer to MSDN or WMI SDK. The WMI SDK documentation contains all the namespaces and classes, beautifully organized based on the categories. All of the members of each and every class present in WMI are thoroughly discussed within the WMI SDK.
In my upcoming articles, I would like to cover as many examples as possible to get several types of information from WMI. We shall also implement both the Windows and Web styles of interfacing through WMI. The topic of “Event Queries” (discussed above) has to be dealt with indepth. I will present a wonderful example of event consuming through windows service using WMI as part of this series.