Understanding WMI Eventing
Windows Management Instrumentation (WMI) enables efficient and scalable monitoring, data collection, and problem detection. However, before you can use it, you need to understand WMI’s data model and eventing infrastructure.
August 23, 2000
Windows Management Instrumentation—Basic
As enterprise systems become increasingly more complex, monitoring the health of your Windows system becomes a crucial management task. To enable efficient and scalable monitoring, you need a mechanism that provides asynchronous notification about the changes occurring in the managed system. Windows Management Instrumentation (WMI) includes a rich eventing infrastructure that enables efficient and scalable monitoring, data collection, and problem detection. However, before you can use the WMI eventing infrastructure, you need to know where to obtain WMI and to understand WMI's data model and eventing infrastructure.
Where You Can Find WMI
WMI is part of the Windows 2000 platform and is available for other Windows platforms. You can download the core WMI components for Windows NT 4.0 and Windows 9x systems from Microsoft's WMI Web site (http://msdn.microsoft.com/downloads/ c-frame.htm?/downloads/sdks/wmi/default.asp). You can also download the WMI software development kit (SDK) from this site. (The Microsoft Platform SDK includes the WMI SDK.) The WMI SDK includes documentation about building WMI components and using WMI eventing.
WMI's Data Model
WMI is based on the notion that you can represent a large variety of management information from different sources to a client in a unified way with a common object schema. You can use this schema to discover, understand, and effectively use various system resources, devices, and applications to monitor the state of your system. The schema is based on the Web-Based Enterprise Management (WBEM) initiative and the Common Information Model (CIM) that the Desktop Management Task Force (DMTF) adopted.
The schema consists of classes. A class is a group of logical elements with the same structure and behavior. Classes are organized in namespaces, which are logical collections of classes representing a specific management domain. For example, the CIMv2 namespace includes classes of managed elements (e.g., the OS, services, applications, device drivers) that represent the computer system. Classes describe the system resources, logical disks, printers, local users, files, processes, and many other elements of interest to a client.
Each class represents a particular category of managed elements. For example, the Win32_Process class represents all running processes. The client can enumerate a class by requesting the list of all elements of the same category or instances of the class within the same namespace.
In addition to classifying managed elements, the data model represents relationships between elements of different classes. You use associations to describe these relationships. Associations fall into a special category of classes that represents links between managed elements. For example, the CIM_ProcessExecutable association class represents the relationship between processes and their executables. Each instance of this class links a process object with the object representing the particular binary file.
WMI's data model defines two categories of objects: static and dynamic. A special database called the schema repository stores the static objects, which represent class definitions, configuration settings and registrations for WMI, and other data that doesn't change over time. Static objects are often used for event subscriptions, which I discuss in the "WMI's Eventing Infrastructure" section. To define static objects, the model uses a special syntax called Managed Object Format (MOF). WMI uses a MOF compiler to store static objects in the repository.
The majority of managed elements in a system aren't static but rather dynamic in nature. The operational state of these elements changes over time and therefore needs to be read on-demand to ensure the latest information is accessed. To access to dynamic objects, WMI uses a three-tier architecture that consists of providers, the CIM Object Manager (CIMOM), and consumers.
Each dynamic class has a provider that creates instances of that class. A provider is a COM component registered in the repository as an instance of the Win32_Provider class. Providers use a set of published interfaces to plug into CIMOM, which Windows systems implement as a service called WinMgmt. CIMOM has exclusive access to the repository, so it acts as a broker between consumers and providers. Consumers are clients that receive data, events, or the results of a method's execution. Examples of consumers include management applications, scripts, and Microsoft Management Console (MMC) snap-ins.
When a consumer issues a request to access an instance of a class, CIMOM receives that request and forwards it to the provider based on the provider registration. The provider supplies the requested data according to the class specification. If the consumer request includes a query, a built-in query engine parses and optimizes the query statement before contacting the provider.
WMI recognizes four types of providers: instance, method, event, and class. Each type of provider implements a subset of provider interfaces specific to the provider's function. Instance providers typically provide the static data needed to create an instance of a class. The data conforms to the class specification, which defines the class' structure and the semantics of that class' properties. Method providers implement a class' defined methods, and event providers raise a class' events. Class providers create new classes dynamically, then create instances of those classes.
You must use a special COM object to implement the class provider. Typically, you use class providers to access data sources whose object schema can dynamically change. For example, the WMI Active Directory provider is a class and instance provider because the schema in Win2K's Active Directory (AD) can change (e.g., new classes might be added) at any time. The class provider maps the native object schema to the equivalent WMI classes. Because you can model virtually all managed elements with fixed, unchanging schema, building class providers is generally not necessary. Instance providers are by far the most commonly written WMI providers.
In WMI's three-tier architecture, CIMOM isolates consumers from the details of data and event provision. As a result, consumers don't have to know which provider is responsible for which data. They only need to request specific objects or events in the model. CIMOM then automatically forwards the request based on the request's parameters and the provider registrations in the repository.
WMI's Eventing Infrastructure
To understand WMI eventing, you must recognize that each dynamic instance of an object in a namespace represents the current state of the underlying managed element. Consequently, the namespace as a whole represents the current state of the managed domain. For example, CIMv2 represents the computer system's current state. A computer system's state constantly changes because many of its parameters are volatile.
Microsoft designed the WMI eventing infrastructure as a notification mechanism for changes in the underlying model. The event subsystem in CIMOM delivers information about events to the consumer through asynchronous notifications. The eventing model includes two types of events: extrinsic and intrinsic.
Extrinsic events are occurrences of certain predefined conditions in the managed system. Examples of extrinsic events are system reboots, user logons, critical errors, and network congestion. Each type of extrinsic event is a separate class. For example, the Win32_PowerManagementEvent class defines events that report when the system switches to or from the Standby mode. Each notification about a power-management event results in the creation of an instance of that class object.
Intrinsic events indicate a change in a managed or class object. Contrary to extrinsic events, each intrinsic event class represents a large category of changes. For example, the _InstanceModificationEvent class defines the structure of the event object generated when any part of any existing instance changes. As a result, a small number of generic classes can represent changes within a large collection of objects of different types. The CIMv2 namespace alone includes 600 classes and about 3000 properties.
Unlike instances of regular class objects, event objects are transient. They "live" only while being delivered to the consumer. Therefore, you can't enumerate all the events of a particular class. If you're interested in a particular event, you can use an event consumer.
The event consumer is a client application that is interested in a particular event. It expresses its interest by registering an event filter, which defines the event's parameters. Using the WMI Query Language (WQL), the filter defines specific events of interest. (For information about WQL, see the Web-exclusive sidebar "WMI Query Language" on the Win32 Scripting Journal Web site at http://www.win32scripting.com/.) The request to receive events is called the event subscription. The event source generates the event only if the event matches one of the registered filters and if outstanding event subscriptions exist for the event.
Listing 1, page 14, contains a script with an event filter that notifies you when the NT event log receives a new entry. The script's first line performs most of the WMI-related work. Within the GetObject call, you specify the moniker for WMI, winmgmt, followed by a path to the machine you want to connect to. In this case, the period after the double backslashes specifies the local machine, but you can specify any valid computer name or IP address if you want the script to work with a remote machine. The rest of the path (i.e., rootcimv2) specifies the WMI namespace to connect to. As mentioned earlier, rootcimv2 is the standard location for the classes describing the current state of the local machine.
Having connected to WMI, the rest of the line executes the ExecNotificationQuery statement, which has one parameter: a WQL query string that defines the events you're requesting. In this case, you're requesting events that represent the creation of new instances of the Win32_NTLogEvent class. Each instance represents an event entry in an NT event log file. When the NT system writes a new entry to a log, WMI sees that entry as the creation of a new instance and notifies the script of this occurrence by sending an _InstanceCreationEvent object to the script. This query reports all events written to all event logs, including the Security log file, which requires a special OS privilege to access the Security log file. As a result, the GetObject call must include the {(Security)} statement to enable this privilege. If you don't include this statement, you'll receive an Access denied message. If the script's users don't have this privilege (e.g., they aren't an Administrator on the machine), this statement won't give them that privilege; the statement only enables the privilege for those who already have it assigned to them.
The rest of the script simply waits for new events to come in and prints the message property of the event instance (an instance of Win32_NTLogEvent) that it received within the _InstanceCreationEvent object.
The script in Listing 1 will notify you about entries as long as it runs—that is, you're creating a temporary event subscription. These subscriptions don't require special registration. Any application or script connected to WMI can receive events by simply calling ExecNotificationQuery. However, constantly running the script in anticipation of an event is often inconvenient. Launching a script when the event occurs—that is, creating a permanent event subscription—is typically more desirable. These subscriptions consist of a group of static objects that include a logical consumer, an event filter, and an association between the two.
For example, Listing 2 contains a fragment of the MOF syntax that registers a permanent event subscription by creating these three objects in the repository. The SMTPEventConsumer, _EventFilter, and _FilterToConsumerBinding classes already exist in the repository, so you just need to set the classes' properties with instance definitions. Each section in this fragment defines an instance you'll be creating in the WMI repository.
The instance of the SMTPEventConsumer class defines what you want in the email message when an event occurs. This class has many properties, but this example only fills in those required to do the job. The rest of the properties will be left empty. The Name property is key because it uniquely identifies this instance from other instances. (You might be sending email to several different people for different events.) Thus, the Name property needs to be a unique string that describes the filter's purpose. The ToLine and Subject Properties are the recipient's email address and the message's subject line, respectively. The Message property contains what you want to say in the body of the email message. You can use the standard %% delimiters to include property values from the event in the message. In this case, the email message body includes the name of the disk that is low on free space. Finally, the SMTPServer property specifies the name of your email server. The consumer needs this information so that it knows where to send the email message.
The instance of the _EventFilter class defines the event you're watching for. Like the previous instance, the Name property contains a unique string to identify this event-filter instance. The Query property contains the event query. In this case, the query watches for disks (represented by the Win32_LogicalDisk class) that drop below 5MB of free space. This event will only fire when a disk transitions from a state of having more than 5MB of free space to a state having less than 5MB of free space. The WITHIN clause in the query specifies that WMI check for this transition every 5 minutes (300 seconds). The QueryLanguage property specifies the query language you want to use. Currently, WQL is the only query language that you can use for WMI.
At this point, you've defined the event (any disk dropping below 5MB of free space) and the action you want to take (WMI sends an email message to the specified user) if that event occurs. Now, you just need to link the _EventFilter and SMTPEventConsumer instances together. You can create this link with an instance of the _FilterToConsumerBinding class. To define the _FilterToConsumerBinding instance, you need to specify three properties: Filter, Consumer, and DeliverSynchronously. In the Filter property, you specify $FILT, which represents the _EventFilter instance you previously defined. In the Consumer property, you specify $CONS, which represents the SMTPEventConsumer instance you previously defined. In the DeliverSynchronously property, you specify FALSE, which means you want the events sent asynchronously.
Because the model stores permanent event subscriptions in the repository, they're independent from the event object's typical short life cycle. As a result, permanent event subscriptions can survive system crashes and machine reboots.
To use the code in Listing 2, you need to set up the SMTP consumer. (Although Win2K ships with the SMTP consumer, the consumer isn't set up by default.) Follow these steps to set up the consumer:
Type or copy the code in Listing 2 into Notepad, and save it in the winntsystem32wbem folder as email.mof.
Fill in the appropriate properties in the SMTPEventConsumer instance, and save the changes.
At the command prompt, change the directory to winntsystem32
wbem.To register the SMTP consumer with WMI, type
MOFCOMP N:rootcimv2 smtpcons.mof
at the command prompt. MOFCOMP is a standard tool that comes with WMI that reads MOF files and places the schema within them into the WMI repository.
To compile your event registration instances, type
MOFCOMP N:rootcimv2 email.mof
at the command prompt.
After you complete these steps, WMI will monitor your disks. You can test the script by copying several large files onto a disk on your system to trigger the event. Because this registration is permanent, the Code Library on the Win32 Scripting Journal Web site contains code that you can use to delete all these registrations. If you don't remove them, you'll always receive an email message every time your free disk space gets low.
Use WMI Eventing
So far, I've introduced you to WMI's data model and eventing infrastructure. I've also shown you how to define temporary event subscriptions and permanent event subscriptions. Next month, I'll show you how to use WMI eventing to monitor a crucial application.
Printed with permission from Microsoft
About the Author
You May Also Like