Introduction
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. If you have questions, or a query that you would like to share, please leave a comment at the bottom of the page.
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):
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 = 608
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 608.
Query text:
Select * From Win32_Process
Where Priority > 8
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 8.
Query text:
Select * From Win32_Process
Where WriteOperationCount < 1000
WMI namespace: Root\Cimv2
.
Comment:
This query returns all Win32_Process
instances where the WriteOperationCount
is less than 1000.
Query text:
Select * From Win32_Process Where ParentProcessId <> 884
Select * From Win32_Process Where ParentProcessId != 884
Select * From Win32_Process Where Not ParentProcessId = 884
WMI namespace: Root\Cimv2
.
Comment:
All three queries return Win32_Process
instances where ParentProcessId
is not equal to 884.
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. On my computer, 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_NetworkAdapter
and 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_Process
property 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. __Superclass
is 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.