With the release of Exchange 2000 Server in October 2000, Microsoft introduced three Windows Management Instrumentation (WMI) providers to monitor the Exchange server state, the Exchange cluster state, and mail queues. (For information about these providers, see the Microsoft white paper "Automating Exchange 2000 Management with Windows Script Host" at http://www.microsoft.com/technet/treeview/default.asp?url=/technet/prodtechnol/exchange/exchange2000/maintain/featusability/ex2kwsh.asp?frame=true.) With the release of Exchange 2000 Service Pack 2 (SP2) in December 2001, Microsoft added two new WMI providers to manage the Message Tracking Logs and the DSAccess components. Let's take a look at these WMI providers and review their capabilities, then discuss how to use them in Windows Script Host (WSH) 5.6.
What Is WMI?
WMI is the Microsoft implementation of the Common Information Model (CIM) initiative that the Distributed Management Task Force (DMTF) developed. The DMTF is an association of computer and software companies (e.g., Microsoft, Novell, Cisco Systems, Hewlett-Packard—HP) that's developing standards in the enterprise-management space. Managing large enterprises with many computers and diverse software environments can be challenging. To unify and simplify management techniques, the DMTF defined CIM to represent real-world manageable entities. The CIM object data model uses terms and semantics that are common to all constructors and software developers.
WMI includes real-world manageable components from the DMTF standard, along with specific extensions that represent various Windows components. Moreover, WMI exposes a collection of COM scriptable objects that let applications take advantage of the management information.
As part of their installation process, most of the Microsoft applications available today (e.g., Windows XP, SQL Server 2000, Exchange 2000, Office 2000, Internet Explorer—IE—5.0 and later) extend the standard CIM object model to add the representation of their manageable entities in the CIM repository. This representation, called a class, exposes information through properties and permits the execution of actions through methods. Access to the manageable entities occurs through a software component called a provider.
When you enable Message Tracking on an Exchange 2000 server, all messages that go through the server are logged in a shared directory. Through the Message Tracking Center, you can use Exchange System Manager (ESM) to examine this directory's contents, as Figure 1 shows.
The Message Tracking Center lets you track messages by sender, target recipients, server name, and message ID. You can select a window time (e.g., start date, end date) for the selection. Before Exchange 2000 SP2, the Message Tracking Center was the only easy way to perform such tracking. Now you can use WMI to retrieve the same information when you install SP2.
WMI's ExchangeMessageTrackingProvider gives you read-only access to messages logged in the Exchange Message Tracking system. This provider supports a single class—called the Exchange_MessageTrackingEntry class—which is a template that represents a message-tracking entry. The class provides a set of properties with which to structure message-tracking information. Table 1 shows the Exchange_MessageTrackingEntry class properties. Note that this class doesn't expose any methods.
For security and organizational reasons, the CIM repository is logically divided into namespaces. The namespace notion is important when you're locating the classes with which you want to work because the classes always reside in a particular namespace. In this case, the Exchange_MessageTrackingEntry class resides in the Root\MicrosoftExchangeV2 namespace.
Using WSH to Extract Information from WMI
By developing a WSH script on top of the WMI COM objects, you can retrieve the same set of information that you accessed through the Message Tracking Center. Web Listing 1 (http://www.exchangeadmin.com, InstantDoc ID 27211) shows the script GetCollectionOfInstances.wsf. This script uses the WSH 5.6 command-line parsing features. For information about this updated WSH version, see "Secure Script Execution with WSH 5.6," August 2002, http://www.winscriptingsolutions.com, InstantDoc ID 25644. The command-line parameters that the script supports are as follows:
- WMI Class specifies the WMI class to use.
- The /Machine option specifies which WMI system to connect to (LocalHost is the default).
- The /User option specifies the user ID that will perform the remote connection.
- The /Password option specifies the password to perform the remote connection.
- The /NameSpace option specifies which WMI namespace to connect to (Root\CIMv2 is the default).
GetCollectionOfInstances.wsf is written so that it isn't specifically related to the Exchange 2000 WMI classes. The only parameter that the script requires is the WMI class that represents the type of management information you want to retrieve. In my example, I use the Exchange_MessageTrackingEntry class, but you can use another WMI class (e.g., Win32_Service). Of course, you must use the /NameSpace option to select—based on the class location in the CIM repository—the correct CIM repository namespace.
After defining the command-line parameters (at callout A in Web Listing 1) and parsing those parameters (at callout B in Web Listing 1), the script creates the WMI connection (at callout C in Web Listing 1). The connection creates an SWbemServices object, which is contained in the objWMIServices variable. This object exposes several methods to retrieve WMI information from the manageable entities. (You can find complete details about this WMI scriptable COM object at http://msdn.microsoft.com/library/en-us/wmisdk/wmi/scripting_api_for_wmi.asp.) The script uses the SWbemServices object's InstancesOf method to request all instances available from the class given on the command line. An instance is the WMI representation of a real-world manageable component, which is built from a WMI class. In this case, each instance—part of a collection—will represent a message-tracking entry. If one or more instances are available, the script performs a For Each...Next statement (at callout D in Web Listing 1) to enumerate the collection of the retrieved instances.
To display the property values, the script retrieves all exposed properties for each instance, thereby producing a collection of properties that are enumerated in a For Each...Next loop. During this loop, for each property exposed by the class given on the command line, the script invokes the DisplayFormattedProperty() function to display the data content in a suitable form.
Web Figure 1 shows sample output from running the WSH script. You might notice that some entries contain a number. To find complete information about property details, such as syntax and meaning, I recommend searching the Microsoft Developer Network (MSDN) Library at http://msdn.microsoft.com/library/en-us/wss/wss/_wmiref_cl_exchange_messagetrackingentry.asp.
WQL Data Query
GetCollectionOfInstances.wsf retrieves all Exchange_MessageTrackingEntry instances available. To do so, the script uses the
Set objWMIInstances = _ objWMIServices.InstancesOf _ (strWMIClass)
line, which uses the SWbemServices object's InstancesOf method. By using another method of the SWbemServices object that makes use of a WMI Query Language (WQL) data query, you can select only some Exchange_MessageTrackingEntry instances. The updated line would appear as follows:
Set objWMIInstances = _ objWMIServices.ExecQuery _ (strWQLQuery)
Note the modification of the variable name from strWMIClass to strWQLQuery. Although changing the variable name isn't mandatory (the coded script logic remains exactly the same), best practice is to use a variable name that reflects the content. If you change this variable name, make sure you change it throughout GetCollectionOfInstances.wsf.
After the script is ready, you need to formulate the WQL query. WQL is a subset of standard ANSI SQL, with minor semantic changes. Users with rudimentary SQL knowledge should be able to understand a basic WQL query, such as the one I use here. To formulate the WQL data query, you would use the following (on one line) at the command line:
C:\>GetCollectionOfInstances.wsf "Select * From Exchange_ MessageTrackingEntry" /NameSpace:Root MicrosoftExchangeV2
Using the WQL data query
Select * From Exchange_ MessageTrackingEntry
produces the same output as you see in Web Figure 1. However, using the WQL query
Select * From Exchange_ MessageTrackingEntry Where SenderAddress='[email protected] MyOrganization.com'
lists only the Exchange_MessageTrackingEntry instances that have a SenderAddress equal to [email protected] For more information about WQL, see the MSDN Library at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/sql_for_wmi.asp and http://msdn.microsoft.com/library/en-us/wmisdk/wmi/querying_with_wql.asp.
The DSAccess Provider
Exchange 2000's DSAccess component manages various Exchange components' access to Active Directory (AD). DSAccess also caches AD requests to improve performance. Because AD is a crucial component of Exchange 2000, you must closely monitor which AD servers Exchange 2000 uses. Having too many Exchange 2000 servers working from the same AD servers can seriously affect system performance. (For more information about the DSAccess component, see "Exchange 2000 SP2's DSAccess Component," July 2002, http://www.exchangeadmin.com, InstantDoc ID 25330.)
After you install Exchange 2000 SP2, ESM displays which AD domain controller (DC) the Exchange 2000 server is using, as Figure 2 shows. Besides this UI extension, Microsoft implemented in SP2 a WMI provider called the ExchangeDsAccessProvider, which supports one WMI class called the Exchange_DSAccessDC class. Essentially, this provider—with its supported class—retrieves the same set of information as the ESM UI. However, because of WMI capabilities, monitoring the DSAccess state—an impossibility from ESM—becomes possible because you can develop custom script logic to monitor the DSAccess state. Table 2 lists the Exchange_DSAccessDC class properties. Note that this class doesn't expose any methods.
The use of the Exchange_DSAccessDC class with GetCollectionOfInstances.wsf permits the retrieval of information that the DSAccess component currently uses. Retrieving this information programmatically is useful. However, generating an event when these Exchange_DSAccessDC instances are modified is much more interesting. The script GenericEventAsyncConsumer.wsf, which Web Listing 2 shows, uses WMI event capabilities to achieve such functionality.
GenericEventAsyncConsumer.wsf exposes nearly the same command-line arguments as GetCollectionOfInstances.wsf. The only difference is in the first parameter. Whereas GetCollectionOfInstances.wsf uses the WMI Class parameter to specify the WMI class to use, GenericEventAsyncConsumer.wsf uses the WQLQuery parameter, which specifies a WQL event query.
In GetCollectionOfInstances.wsf, I used the SWbemServices object's ExecQuery method instead of its InstancesOf method to make a small script modification. In GenericEventAsyncConsumer.wsf, I use the SWbemServices object's ExecNotificationQueryAsync method. This method performs a WQL query, but instead of seeking a particular instance of a class, this method waits for a specific WMI event that matches the WQL query. For example, to capture any modification event related to the Exchange_DSAccessDC instances, you would use a WQL query such as the following:
Select * From __InstanceModificationEvent Within 5 Where TargetInstance ISA 'Exchange_DSAccessDC'" /NameSpace:Root MicrosoftExchangeV2
Translated into English, this query says to select all modifications with a polling frequency of 5 seconds when the modified instance is using an Exchange_DSAccessDC class.
The uniqueness of the ExecNotificationQueryAsync method lies in its execution. Instead of returning a collection of instances that match the WQL query directly on the same line (as the ExecQuery method does), the method returns the results asynchronously. The results return in a parallel routine (i.e., thread) while the script continues its execution after the invocation of the ExecNotificationQueryAsync method.
The parallel thread resides in the SINK_OnObjectReady() subroutine, which provides the instances that match the WQL query. The WMI event subsystem performs one call per modified instance. The ExecNotificationQueryAsync method, with the help of an SWbemSink object, identifies this routine as the asynchronous routine. (For more information about the SWbemSink object, see http://msdn.microsoft.com/library/en-us/wmisdk/wmi/swbemsink.asp.) The SWbemSink object uses the SINK_ label as a pointer to a series of subroutines that the WMI event subsystem supports. One of these WMI events is the OnObjectReady event. This event delivers the instances that match the submitted WQL query—which explains the name of the SINK_OnObjectReady() subroutine, a concatenation of the label given during the SWbemSink object creation and the supported WMI event subroutine name. For this reason, I won't talk about a WQL data query (as I did with GetCollectionOfInstances.wsf) but rather a WQL event query.
To receive a notification for any changes that occur to any instances of the Exchange_DSAccessDC class, you must use the following (on one line) at the command line:
C:\>GenericEventAsyncConsumer.wsf "Select * From __InstanceModificationEvent Within 5 Where TargetInstance ISA 'Exchange_DSAccessDC'" /NameSpace:Root\Microsoft ExchangeV2
To run this script in the background in your production environment, you can run the code in a service context. The Microsoft Windows 2000 Server Resource Kit contains tools (e.g., srvany.exe) that you can use for this purpose. Make sure that you use the correct security context for your service (the service account must have network-access capabilities), and ensure that the script sends an alert in a form other than a message display. For example, you can log an event in the Application event log or send an email message through an SMTP relay within your company. For coding examples, refer to the Microsoft white paper "Automating Exchange 2000 Management with Windows Script Host."
Web Figure 2 shows sample output from GenericEventAsyncConsumer.wsf. For complete property details, such as syntax and meaning, see the Microsoft article "Exchange_DSAccessDC Class" (http://msdn.microsoft.com/library/en-us/wss/wss/_wmiref_cl_exchange_dsaccessdc.asp).
A Good Investment
Understanding the underlying technology, such as the CIM repository object model, is essential to grasping how WMI represents real-world manageable entities. Mastering scripting or programming techniques is useful because it permits the development of customized business logic. Finally, understanding the managed components' behavior is important because it determines how you need to set up your customized logic or rules to properly handle unexpected situations.
Microsoft is expanding the use of WMI in many of its applications. Exchange 2000's use of WMI represents significant progress toward making management information easily accessible from any application in a standardized way. WMI is powerful and complex. Today, the CIM repository contains more than 600 classes and exposes more than 3000 properties to offer a versatile Windows-management solution. Although WMI isn't always easy to understand, learning how to use it is a good investment.