Today's complex OSs—including Windows—perform many tasks at the same time and generate many events. System users trigger additional events. For instance, a user or an administrator might perform some system configuration changes, disconnect the power plug from the machine, or shut down the OS. Each of these actions triggers one or more events. From a management perspective, the ability to capture and audit these events has great potential value. For example, you might want to write a script that would notify you if someone makes a certain system configuration change. If you submit the appropriate Windows Management Instrumentation (WMI) Query Language (WQL) query, you can catch OS events.
To submit the WQL event queries that I present here, you can use any application that can consume WMI events. Microsoft .NET application developers can use the System.Management classes available from the Windows .NET Framework. Administrators with some scripting knowledge can use a simple WMI script. If you have no programming experience, you can use the wbemtest.exe tool that's included in any WMI-capable Windows version (Windows NT 4.0 and later). If your Windows infrastructure already has enterprise management software such as Microsoft Operations Manager (MOM) or HP OpenView in place, you can catch WMI events from this software as well.
For the purposes of this article, I use GenericEventAsyncConsumer.wsf, a script that I wrote expressly for the purpose of submitting WQL event queries. You can download GenericEventAsyncConsumer.wsf by going to http://www.winnetmag.com/windowsscripting, entering InstantDoc ID 42371, and clicking the 42371.zip hotlink. The command syntax you use to submit a WQL event query is
GenericEventAsyncConsumer.wsf "WQL event query" \[/NameSpace:Value\] \[/Machine:Value\] \[/User:Value\] \[/Password:Value\]
where WQL event query is the string that represents the WQL event query. The other parameters are optional. The /NameSpace switch specifies the WMI namespace to which you want to submit the query. By default, the script connects to the root\cimv2 namespace. The /Machine switch specifies the system to which you want to connect. By default, the script connects locally. For a remote connection, you must specify values for the /Machine, /User, and /Password switches. You don't need administrative privileges when you submit a query locally, but WMI default security requires administrative privileges when you access WMI information remotely. For more information about how GenericEventAsyncConsumer.wsf submits an event query, see "Exchange 2000 SP2 WMI Updates," January 2003, InstantDoc ID 27211.
To use Wbemtest instead of a script to catch an event, select Run from the Start menu of a Windows Server 2003 or Windows XP computer and type
Click Connect and specify the WMI namespace to which you want to connect in the dialog box that Figure 1 shows. To connect to the local machine, just change the default namespace root\default to root\cimv2. To connect to a remote machine, specify the Universal Naming Convention (UNC) path to the namespace—\\machinename\root\cimv2—and specify the user and password in the Credentials section of the same dialog box. Click Connect. After you've connected Wbemtest to the namespace, click Asynchronous, then click Notification Query. A box will open in which you can enter your WQL event query.
Events to Query
Now that you know how to submit queries to capture system events, you might wonder which events to capture. Windows 2003 WMI exposes more than 600 classes and 3000 properties supported by more than 80 providers (Windows 2000 has fewer classes and properties and only 30 providers). Obviously, I can't examine all these in one article. Therefore, I concentrate on the following typical events supported by the WMI event providers (i.e. specialized providers that Microsoft developed to handle system events):
- Clock events supported by the clock provider available in Windows 2003 and XP
- Power state events supported by the power management provider available in Windows 2003, XP, Win2K, and NT 4.0
- Shutdown and logoff notification events supported by the shutdown provider available in Windows 2003 and XP
- Configuration change notification events supported by the configuration change provider available in Windows 2003 and XP
- Disk volume modification events supported by the volume change provider available in Windows 2003 and XP
Catching Clock Events
Accessing time information in a system is useful for many purposes. For instance, an application might need to start another application at a fixed time each day or perform some operation at a fixed interval (e.g., a cleanup process that must run every hour). The application must be able to access the system time so that it can perform its tasks as scheduled.
Windows 2003 and XP include the Win32 clock provider, which lets you easily access the system time information through WMI. Microsoft implemented this provider as an instance provider and an event provider. As an instance provider, it provides WMI instances representing the time of the system. To do so, the provider supports three WMI classes located in the root\cimv2 namespace: the Win32_CurrentTime class, the Win32_LocalTime class, and the Win32_UTCTime class.
The Win32_CurrentTime class is the parent class (also called a super-class) of the Win32_LocalTime class and the Win32_UTCTime class, which means that Win32_CurrentTime is used as a template to create the two subclasses. All three classes are singleton classes, which means that only one instance of each class is available per system. This restriction makes sense because one OS instance can't have multiple times. The Win32_LocalTime class represents the system's local time. The Win32_UTCTime class returns Universal Time Coordinate (UTC) time, which corresponds with Greenwich Mean Time (GMT). More information about the time classes is available at http://msdn.microsoft.com/library/en-us/wmisdk/wmi/win32_currenttime.asp.
As I mentioned earlier, Windows also implements the Win32 clock provider as an event provider, which works with the __InstanceModificationEvent event class to deliver notification events in response to WQL event queries. The WQL event queries
Select * From __InstanceModificationEvent Where TargetInstance ISA 'Win32_LocalTime'
Select * From __InstanceModificationEvent Where TargetInstance ISA 'Win32_UTCTime'
trigger a notification every time the local time and UTC time change. Because both target instances change every second, WMI will notify the subscriber (i.e., the application that submits the event query) every second.
Note that the queries don't use the WITHIN condition, although they could. WQL event queries that use WITHIN don't leverage the WMI event provider capabilities. When a WQL event query specifies the WITHIN condition, it's requesting the core WMI subsystem to execute the query. In such a case, the core WMI subsystem, with the help of the provider that supports the requested target instance, polls for a change in status and waits until the end of the polling cycle to notify the subscriber of any change. Although this approach works fine, it's slower than an event query supported by an event provider. If you omit the WITHIN condition, a WMI event provider handles the WQL event query and returns notifications as changes occur. The WMI subscriber doesn't have to wait until the end of a polling cycle to be notified; the notification immediately follows the change.
You can elaborate on the previous queries to get a notification every minute instead of every second with a query such as
Select * From __InstanceModificationEvent Where TargetInstance ISA 'Win32_UTCTime' AND TargetInstance.Second=0
Every time the Second WMI property is equal to 0 (i.e., every minute), the subscriber receives notification. You can obtain this result with any of the three classes that the Win32 clock provider supports.
If you want to get a notification at a specific time, you just need to elaborate a little more on the query. The query
Select * From __InstanceModificationEvent Where TargetInstance ISA 'Win32_UTCTime' AND TargetInstance.Second=17 AND TargetInstance.Minute=23 AND TargetInstance.Hour=15 AND TargetInstance.DayOfWeek=2 AND TargetInstance.WeekInMonth=2 AND TargetInstance.Quarter=2
generates a notification at 17:23:15 UTC time every Tuesday of the second week of April, May, and June.
WMI also supports using the __IntervalTimerInstruction and __AbsoluteTimerInstruction system classes documented at http://msdn.microsoft.com/library/en-us/wmisdk/wmi/__intervaltimerinstruction.asp and http://msdn.microsoft.com/library/en-us/wmisdk/wmi/__absolutetimerinstruction.asp, respectively, to access time information. I won't dig into the usage of these classes because they require more WMI experience to use than do the Win32 clock provider classes.
Catching Power Management Events
Available in Windows 2003, XP, Win2K, and NT 4.0, the power management provider is an event provider that supports the Win32_PowerManagementEvent event class in the root\cimv2 namespace. The power management provider triggers a WMI event notification to every subscriber registered to receive power management event notifications. The Win32_PowerManagementEvent class is documented at http://msdn.microsoft.com/library/en-us/wmisdk/wmi/win32_powermanagementevent.asp. The power management provider isn't an instance provider and therefore doesn't expose information about the power devices themselves. To gather information about the power devices, you must refer to other classes, such as Win32_Battery, Win32_CurrentProbe, Win32_PortableBattery, and Win32_UninterruptiblePowerSupply.
The line at callout A in Figure 2 shows the WQL event query to use to receive all power management events. The easiest way to test the query is to run GenericEventAsyncConsumer.wsf or Wbemtest on a laptop. After you've submitted the query, switch the laptop into standby or hibernate mode, then switch it back on. You'll see the three events that Figure 2 shows. Each time a power management event occurs, the script receives the event, which is represented by an instance of the Win32_PowerManagementEvent class. This class exposes the EventType property, whose value corresponds to the power management event type (e.g., Entering Suspend=4, Resume from Suspend=7, Power Status Change=10, OEM Event=11, Resume Automatic=18).
Note that if you remove the laptop's power plug, the laptop will run on the battery and trigger power management event type 10. This event type is useful for applications that must perform specific tasks when the power status of the computer changes.
Catching Shutdown Events
Like the power management provider, the shutdown provider supports only one event class: Win32_ComputerShutdownEvent. Only available in Windows 2003 and XP, the Win32_ComputerShutdownEvent class is located in the root\cimv2 namespace and documented on MSDN at http://msdn.microsoft.com/library/en-us/wmisdk/wmi/win32_computershutdownevent.asp. This event class represents events that occur when a computer has begun a shutdown process. To receive a computer shutdown notification, a subscriber must use the WQL event query that Web Figure 1 (http://winnetmag.com/windowsscripting, InstantDoc ID 42371) shows on a remote system. Obviously, you can't monitor this event locally because the local system is shutting down.
Web Figure 1 also shows the query results after you request a system reboot or shutdown. The first event is of type 0 (logoff); the second event is of type 1 (shutdown or reboot). You can see that the shutdown provider notifies subscribers of logoff events in addition to detecting OS shutdowns. Like the power management event, the shutdown event is useful for an application that must execute some specific tasks on a central system when a user logs off or shuts down his or her machine.
Catching Configuration Change Events
Microsoft implemented the configuration change provider as an event provider in Windows 2003 and XP. This provider and the Win32_SystemConfigurationChangeEvent event class indicate when the system's device list has been refreshed. Located in the root\cimv2 namespace, the Win32_SystemConfigurationChangeEvent event class is the only class supported by the configuration change provider and is documented at http://msdn.microsoft.com/library/en-us/wmisdk/wmi/win32_systemconfigurationchangeevent.asp. The Win32_SystemConfigurationChangeEvent event class is a subclass of the Win32_DeviceChangeEvent superclass, which is also the parent class of the Win32_VolumeChangeEvent class (which I discuss next).
To subscribe to the Win32_SystemConfigurationChangeEvent event class, you must submit the WQL event query that Figure 3 shows. You'll then receive a notification when you add, remove, or reconfigure a system device. For instance, if you use GenericEventAsyncConsumer.wsf to submit the query, then connect a USB device to your Windows 2003 or XP system, you'll get results similar to those that Figure 3 shows. The EventType property indicates the type of device change that has occurred (Configuration Changed=1, Device Arrival=2, Device Removal=3, Docking=4).
The EventType property doesn't indicate which device triggered the event. In addition, an EventType value of 1 (configuration changed) can refer to almost anything related to the system configuration, including IRQ settings, COM ports, or BIOS version. If you need more detailed information about the current hardware settings, you must write an application or a script that queries the Win32_Processor, Win32_PhysicalMemory, Win32_DMAChannel, and Win32_IRQResource classes; run the script before and after the changes; and compare the two sets of results.
Catching Volume Change Events
Available only in Windows 2003 and XP, the volume change event provider supports the Win32_VolumeChangeEvent event class available in the root\cimv2 namespace and documented at http://msdn.microsoft.com/library/en-us/wmisdk/wmi/win32_volumechangeevent.asp. Like the Win32_SystemConfigurationChangeEvent class, the Win32_VolumeChangeEvent class's parent class is the Win32_DeviceChangeEvent superclass and Win32_VolumeChangeEvent exposes the EventType property. (The EventType property is defined at the level of the Win32_DeviceChangeEvent class and is inherited by both Win32_SystemConfigurationChangeEvent and Win32_VolumeChangeEvent.)
Win32_VolumeChangeEvent represents events related to adding or removing drive letters or to mounting or dismounting drives on a computer. The event class doesn't support network drives. Web Figure 2 shows the query you submit to receive drive-change events. Web Figure 2 also shows the results you'd see if you changed the drive letter of a volume from E to Z. EventType 3 indicates that a drive is removed; EventType 2 means that a drive is added.
The WQL event queries that I discuss in this article are just a few examples of the thousands of queries that you can formulate with WMI. Managing a system isn't just gathering information about the manageable components; it's also keeping tabs on important events in the life cycle of a system or an application. Understanding enough about WMI to trigger a notification when something occurs in the system will pay dividends as you seek to increase the manageability of your enterprise Windows network.