WQL

email me

Windows Management Instrumentation (WMI) is the Microsoft implementation of WBEM, an industry initiative that attempts to facilitate system and network administration. WMI was introduced with Windows 2000, and has since evolved to include data about the most Windows resources, both hardware and software.

There are several ways in which you can access WMI data, and most of them use WQL queries. You can use several tools to execute WQL queries, the most accessible of which is a tool called WMI Tester (wbemtest.exe) – it is installed with Windows.

This article is a short tutorial that attempts to shed some light on several WQL aspects through a series of example WQL queries. I grouped the queries by their type.

  • Object Queries
  • Event Queries
  • Schema Queries

Most of the queries presented here will get all WMI object properties (e.g., Select * …) in order to make the queries more readable. If you are familiar with SQL, you are probably aware of the recommendation that you should never use Select * (unless you really need all the columns) in order to make queries more efficient. I haven’t been able to confirm that selecting only specific properties has any impact on query efficiency in WQL, but you can easily replace * with property names.

WMI Tester (Wbemtest.exe) is a tool that provides the basic functionality for executing WQL queries. You can run it by typing ‘wbemtest.exe‘ in the Run box.

This opens the WMI Tester.

You first need to connect to the WMI namespace that contains the class you want to query (Root\Cimv2 in most cases). Click the Connect button.

Run the query by clicking the ‘Query’ or ‘Notification Query’ button

Enter the query text.

Click the ‘Apply’ button. This opens a window with the query results:

If the query is invalid, you will receive an error message.

 

Object Queries

Object queries are used to get information about system resources.


Query text:

Select * From Win32_Process

WMI namespace: Root\Cimv2.

Comment:

This is probably the WQL query most often found in various WMI articles and textbooks. It simply gets all the instances of a WMI class named Win32_Process which represents Windows processes. If you are interested in the properties of Win32_Process, see here.


Query text:

Select * From Win32_Process 
Where ProcessId = 999

WMI namespace: Root\Cimv2.

Comment:

If you don’t really want all Windows processes, you can qualify your query using the WHERE clause. This clause looks like this:

Where PropertyName Operator PropertyValue

where Operator is one of the WQL relational operators. The above query will return Win32_Process instances with process ID equals to 999.


Query text:

Select * From Win32_Process 
Where Priority > 9

WMI namespace: Root\Cimv2.

Comment:

One of the WQL relational operator is ‘>’ (greater than). The above query returns all Win32_Process instances with Priority greater than 9.


Query text:

Select * From Win32_Process 
Where WriteOperationCount < 10000

WMI namespace: Root\Cimv2.

Comment:

This query returns all Win32_Process instances where the WriteOperationCount is less than 10000.


Query text:

Select * From Win32_Process Where ParentProcessId <> 999
Select * From Win32_Process Where ParentProcessId != 999
Select * From Win32_Process Where Not ParentProcessId = 999

WMI namespace: Root\Cimv2.

Comment:

All three queries return Win32_Process instances where ParentProcessId is not equal to 999.


Query text:

Select * From Win32_Service

WMI namespace: Root\Cimv2.

Comment:

Another commonly seen query that retrieves all information about Windows Services. See here for details about the Win32_Service class. Note that this query returns all class instances. Sometimes this is just what you want, other times it is not, and yet other times, this is something you should definitely avoid.


Query text:

Select * From Win32_Service 
Where Name = "MSSQL$SQLEXPRESS"

WMI namespace: Root\Cimv2.

Comment:

Here is an improved query – it returns only Win32_Service instances that have the Name property equal to “MSSQL$SQLEXPRESS”. It happens that Name is the key property for the Win32_Service class, so the returned WMI object collection will have 0 or 1 item, but in general, if you qualify a query with a WMI class property value, you get all class instances where the property matches the entered value.

Query text:

Select * From Win32_Service 
Where DisplayName = "Plug and Play"

WMI namespace: Root\Cimv2.

Comment:

Here is a caveat. If you are familiar with Windows services, you know that you can access service information using Services.msc (Start > Run > Services.msc). When you open that applet, the text in the Name column is not equal to the Win32_Service.Name value. It is equal to the Win32_Service.DisplayName property value, so if you want to get services by their Services Control Panel applet name, use the above query.


Query text:

Select * From Win32_Service 
Where PathName = "C:\\WINDOWS\\system32\\inetsrv\\inetinfo.exe"

WMI namespace: Root\Cimv2.

Comment:

Here is another caveat. If a property value contains backslashes, you need to escape them by putting another backslash before (or after) each of them – otherwise, you get the ‘Invalid query’ error.


Query text:

Select * From Win32_Service 
Where Name Like "%SQL%"

WMI namespace: Root\Cimv2.

Comment:

What if you don’t know the exact service name (or display name)? This is where the LIKE WQL operator comes in handy. Just like in SQL, the ‘%’ meta character replaces any string of zero or more characters, so this query returns all Win32_Service instances where the Name property contains the string “SQL”.


Query text:

Select * From Win32_Service 
Where Name > "M" And Name < "O"

WMI namespace: Root\Cimv2.

Comment:

You can use all WQL operators with string properties. This query returns all Win32_Service instances whose Name is greater than ‘M’ or less than ‘O’. The usual string comparison rules apply.


Query text:

Select * From Win32_Service 
Where ExitCode = "1077"

WMI namespace: Root\Cimv2.

Comment:

The Win32_Process.ExitCode property type is UInt32, but it is enclosed in quotes. WMI will does its best to interpret a string value and convert it to an appropriate type. This doesn’t work the other way – with string properties, you have to use quotes.


Query text:

Select * From Cim_DataFile 
Where Drive = "C:" 
And Path = "\\Scripts\\"

WMI namespace: Root\Cimv2.

Comment:

Cim_DataFile is a WMI class with which you should definitely always use the WHERE clause. ‘Select * From Cim_DataFile’ alone can take hours to complete, because it will return all files on your computer. Note that the Path property doesn’t contain file names or the drive letter which is stored in the Drive property.


Query text:

Associators Of {Win32_NetworkAdapter.DeviceId=1}

WMI namespace: Root\Cimv2.

Comment:

As you can see, Select queries are not the only query type in WQL. Just like Select queries, Associators Of queries can return either WMI objects or class definitions. There is a difference though: Select queries always return a collection of instances of one WMI class, or at least instances of classes that have the same parent class at some level. Associators Of queries, on the other hand, usually return a collection of WMI objects that belong to different WMI classes. One thing that the returned objects have in common is that they are all associated with the WMI object specified in the Associators Of query (enclosed between the curly braces). Note that you have to use the key properties of an object to specify its path, and that there are no spaces between the property name, the equals sign, and the property value. The above query returns instances of the following classes:

  • Win32_ComputerSystem
  • Win32_DeviceMemoryAddress
  • Win32_IRQResource
  • Win32_NetworkAdapterConfiguration
  • Win32_NetworkProtocol
  • Win32_PnPEntity
  • Win32_PortResource
  • Win32_SystemDriver

Query text:

Associators Of {Win32_NetworkAdapter.DeviceId=1} 
Where ResultClass = Win32_NetworkAdapterConfiguration

WMI namespace: Root\Cimv2.

Comment:

Most of the time, you will not need all WMI objects associated with a WMI object. You can narrow the returned collection by specifying the class of the returned objects in an Associators Of query Where clause. The above query returns an instance of Win32_NetworkAdapterConfiguration associated with the source object.


Query text:

Associators Of {Win32_NetworkAdapter.DeviceId=1} 
Where AssocClass = Win32_NetworkAdapterSetting

WMI namespace: Root\Cimv2.

Comment:

WMI classes are associated by a special type of WMI classes, called association classes. Win32_NetworkAdapterand Win32_NetworkAdapterConfiguration objects are associated by instances of the association class called Win32_NetworkAdapterSetting. As you can see, you can also use association class names to limit the returned object collection.


Query text:

References Of {Win32_NetworkAdapter.DeviceId=1}

WMI namespace: Root\Cimv2.

Comment:

You can use a References Of query to examine WMI object associations. Unlike Associators Of queries, References Of queries return only WMI association classes. This query returns instances of the following WMI association classes:

  • Win32_AllocatedResource
  • Win32_NetworkAdapterSetting
  • Win32_PnPDevice
  • Win32_ProtocolBinding
  • Win32_SystemDevices

Event Queries

Event queries are used for WMI event subscriptions.

Query text:

Select * From __InstanceCreationEvent 
Within 5 
Where TargetInstance Isa "Win32_Process"

WMI namespace: Root\Cimv2.

Comment:

This query is also often found in WMI samples. WMI event queries are different from other query types in that they don’t return WMI objects immediately. Instead of that, they are used for subscribing to WMI events, and objects are returned as events arrive. Note the two distinctive characteristics of event queries not present in other query types: the Within clause and the __InstanceCreationEvent class. The Within clause tells WMI how often to poll for events in seconds. In the above query, the polling interval is 5 seconds. WQL event monitoring consumes system resources, so it is important to balance between the need to get events on time and the need not to burden the system. The __InstanceCreationEvent class is one of the classes used only in event queries (other two commonly used classes are  __InstanceModificationEvent and  __InstanceDeletionEvent). An instance of this class is created when a requested event arrives. The __InstanceCreationEvent.TargetInstance property holds a reference to a WMI class that actually triggered the event. In the above query, it is the Win32_Process class, and we can use the TargetInstance property to access its properties.


Query text:

Select * From __InstanceCreationEvent 
Within 5 
Where TargetInstance Isa "Win32_Process" 
And TargetInstance.Name = "Notepad.exe"

WMI namespace: Root\Cimv2.

Comment:

This query monitors the process creation event but only for processes named ‘Notepad.exe’.


Query text:

Select * From __InstanceDeletionEvent 
Within 5 
Where TargetInstance Isa "Win32_Process" 
And TargetInstance.Name = "Notepad.exe"

WMI namespace: Root\Cimv2.

Comment:

Use this query to monitor process deletion events for processes whose Name property is equal to ‘Notepad.exe’. A process deletion event occurs when a process exits. There is one thing you should note about a query like this: if you open Notepad and then quickly close it (within less than 5 seconds), it is possible for WMI to miss that and not report it as an event.


Query text:

Select * From __InstanceModificationEvent 
Within 5 
Where TargetInstance Isa "Win32_Process" 
And TargetInstance.Name = "Notepad.exe"

WMI namespace: Root\Cimv2.

Comment:

This query monitors Win32_Process modification events, not the process modification event. This is an important distinction – if the Windows process entity has a property that is not represented with a Win32_Process WMI class, and if that property changes, WMI will not report the change. Only Win32_Processproperty changes are returned as WMI events.


Query text:

Select * From __InstanceOperationEvent 
Within 5 
Where TargetInstance Isa "Win32_Process" 
And TargetInstance.Name = "Notepad.exe"

WMI namespace: Root\Cimv2.

Comment:

This query monitors all three types of events: creation, deletion, and modification events. The __InstanceOperationEvent class is the parent for the __InstanceCreation__InstanceDeletion, and __InstanceModification classes, and you can use this fact to subscribe to all three event types at the same time. The __InstanceOperationEvent class is abstract (which means that it doesn’t have instances), so the actual event class returned by an event is one of the tree instance classes, and you can find out which one by inspecting its __Class system property. This way, you can determine the event type.


Schema Queries

Schema queries are used to get information about WMI itself and its structure.


Query text:

Select * From Meta_Class

WMI namespace: Any.

Comment:

This is the most basic schema query. You can connect to any WMI namespace and use this query to get all the classes present in it. Meta_Class is a meta class used only in schema queries.


Query text:

Select * From Meta_Class 
Where __Class = "Win32_LogicalDisk"

WMI namespace: Root\Cimv2.

Comment:

This query uses the __Class system property to get the Win32_LogicalDisk class. Schema queries don’t return class instances, but class definitions, and a query like this will return a class definition regardless of whether there are any instances. Why would you want to get a class definition? New WMI classes are added for every new Windows version, and a query like this can check if a class exists on a system.


Query text:

Select * From Meta_Class 
Where __Superclass Is Null

WMI namespace: Any.

Comment:

WMI is organized hierarchically – there is a hierarchy of namespaces as class containers, and there is a hierarchy of classes within each namespace. There is only one top level namespace called ‘Root’, but there is always more than one top level class in a namespace (even when you create a new empty namespace, a number of system WMI classes are created automatically). You can use this query to get all top level classes for a namespace. (This query also works if you use ‘=‘ instead of ‘Is‘.)


Query text:

Select * From Meta_Class 
Where __Superclass = "Win32_CurrentTime"

WMI namespace: Root\Cimv2.

Comment:

For each WMI class, the __Superclass property holds the name of its immediate parent class. You can use this query to return all immediate children classes of a class. Note the quotes around the class name. __Superclassis one of the seven WMI system properties (see details here), and you can use them in schema queries. All except one – the __Dynasty property is a string array, and you can’t use array properties in WQL queries. The above query returns two classes: Win32_LocalTime and Win32_UTCTime, the immediate children of Win32_CurrentTime.


Query text:

Select * From Meta_Class 
Where __Dynasty = "Cim_Setting"

WMI namespace: Root\Cimv2.

Comment:

__Dynasty is another WMI system property – for each class, it holds the name of the top level class from which the class is derived. This query will return all children of Cim_Setting, a top level class situated in the Root\Cimv2 namespace.


Query text:

Select * From Meta_Class 
Where __Class Like "Win32%"

WMI namespace: Root\Cimv2.

Comment:

All WMI classes belong to a schema (or at least they should). For example, classes whose name begins with ‘Cim’ belong to the Cim schema, a group of ‘core and common’ WMI classes defined by DMTF. Classes that begin with ‘Win32’ belong to the ‘Win32’ schema – these classes are derived from Cim classes and extend them. You can use this query to list all classes that belong to the ‘Win32’ schema. The query uses the Like operator – this means, it can’t be used on Windows versions earlier than Windows XP, because the Like operator was added to WQL for XP.


Query text:

Select * From Meta_Class 
Where __This Isa "__Event"

WMI namespace: Any.

Comment:

This is not an event query despite the fact that it uses the __Event class. It is a schema query that lists all child classes (both direct and indirect) of __Event. Note the use of ‘__This’, a special WMI property used in schema queries, and the ‘Isa’ operator.