To learn more about WMI scripting capabilities, see the Microsoft Windows 2000 Professional Resource Kit or Microsoft Windows 2000 Server Resource Kit. You'll find more than 50 WMI-based scripts to manage and report on everything from a target computer's boot configuration to user accounts. Although you can examine the VBScript (.vbs) files in your resource kit installation directory, you need to understand WMI scripting to understand the script's inner workings.
WMI Scripting 101
WMI scripting is a library of automation interfaces that sit on top of the Common Information Model Object Manager (CIMOM). COM-compliant scripting languages (e.g., Windows Script—WS, ActivePerl) use these automation interfaces to access WMI's infrastructure. Wbemdisp.dll is the DLL that implements the WMI automation objects, methods, and properties.
To access WMI through the WMI scripting library, you need to perform three steps that are common to most WMI scripts. First, connect to the Windows Management service, and second, retrieve instances of WMI managed objects. Third, call a method or access a managed object's property. After you understand the interfaces that you use to perform these steps, you'll be well on your way to becoming a WMI scripting guru.
Let's examine a WMI script that demonstrates these three steps in action. Winmgmts.vbs in Listing 1, page 164, is a basic WMI script. You can download the complete listings from Windows 2000 Magazine's Web site at http://www.win2000mag.com/. (Enter 9033 in the InstantDoc text box, go to the Article Info box, and click the 9033.zip file.) The script is powerful and demonstrates most of what you need to know to leverage WMI scripting.
The script initializes two string variables—strComputer and strProcsToKill. The target computer's name is StrComputer; strProcsToKill is a process name that the script uses to identify and kill all running processes with the same name. Notepad.exe is the running process in this case.
The code at callout A in Listing 1 uses WMI's moniker winmgmts to connect to WMI on the target computer and retrieve all Win32_Process class instances. (A moniker is a standard COM mechanism for binding to a COM object.) You can include optional security settings and additional object path components as part of the WMI moniker syntax. (For detailed information about WMI moniker syntax, see http://msdn.microsoft.com/library/psdk/wmisdk/scintro_6tpv.htm.)
The script returns each Win32_Process instance as an SWbemObject in an SWbemObjectSet collection. SWbemObjectSet and SWbemObject are two of several interfaces that the WMI scripting library provides. You can use VBScript's For...Each construct at callout B in Listing 1, page 164, to enumerate SWbemObjectSet because it's a collection.
At callout B, the script performs the last step for accessing WMI. Inside the For...Each loop, the script accesses two properties and one method that the Win32_Process class defines. First, the script echoes the ProcessID and Name properties of each Win32_Process instance. Next, the script compares the current Win32_ProcessName property with the strProcsToKill variable. If the two match, the script calls the Terminate method that the Win32_Process class provides to kill the current instance.
In Listing 1, I leverage two distinct sets of methods and properties. The first set includes methods and properties that the WMI scripting library interfaces provide to connect to WMI, retrieve class instances, and subscribe to events. The second set includes methods and properties that the Common Information Model (CIM) Win32 classes provide (e.g., Win32_Process, Win32_NTEventLog).
To determine the properties and methods that each (of the more than 300) CIM Win32 classes provides, let's examine the Win32_ Process class. In "Windows Management Instrumentation: The Journey Begins," July 2000, I explained that a class is a template that defines how each corresponding instance looks and behaves and that the CIM contains all class definitions for the managed environment. In winmgmts.vbs, each process instance exposes the methods and properties that the Win32_Process class definition implements and inherits. This concept holds true for all defined classes in the CIM. You can use the wbemtest.exe utility to easily explore the defined classes in the CIM. You can also find class information in the WMI software development kit (SDK) documentation.
WMI Scripting Object Model
The WMI Scripting Object Model in Figure 1 shows the primary objects that make up the WMI scripting library. The model's objects provide the methods and properties that you use to access and retrieve WMI objects in your scripts. I use the three-step method to examine how winmgmts.vbs uses the objects that the model provides.
Step 1: Connecting to WMI. The script uses the winmgmts moniker to connect to WMI. This action returns an SWbemServices object. However, rather than creating a reference to the SWbemServices object, the script immediately calls the SWbemServices object's InstancesOf method.
Step 2: Retrieving class instances. The SWbemServices InstancesOf method returns instances of a specified class. In Listing 1, the SWbemServices InstancesOf method returns Win32_Process instances in an SWbemObjectSet, which the objects' relationship in Figure 1 shows. The script initializes a reference variable—wbemObjectSet—to point to the SWbemObjectSet collection that the SWbemServices InstancesOf method returns.
Step 3: Accessing class methods and properties. SWbemObjectSet collections contain CIM class instances that an SWbemObject represents. You can use a For...Each loop to enumerate an SWbemObjectSet collection and thereby access each Win32_Process instance. During each loop iteration at callout B, the wbemObject reference variable is set to each successive Win32_Process instance in the collection. You use SWbemObject to access the methods and properties that a CIM class instance exposes.
Table 1 provides a brief description of each object in the WMI Scripting Object Model and includes a URL that points to the object's documenta-tion on Microsoft's Web site. The referenced documentation provides detailed information about the methods and properties that the corresponding object exposes.
Locator.vbs in Listing 2 is another script that you can use to perform the same task that winmgmts.vbs performs. The primary difference between the two listings is that locator.vbs uses the SWbemLocator object rather than the WMI moniker to obtain an SWbemServices object. This difference also accounts for why locator.vbs uses VBScript's CreateObject function, whereas winmgmts.vbs uses VBScript's GetObject function. Winmgmts.vbs uses GetObject to work with monikers. The WbemScripting.SWbemLocator programmatic identifier (ProgID) in locator.vbs tells CreateObject that you want to create an SWbemLocator object.
Although the scripts in Listings 1 and 2 are functionally equivalent, they demonstrate the different mechanisms that the WMI scripting library provides. Beginners might find the moniker syntax confusing at first and therefore prefer to use SWbemLocator. From a functional perspective, the ConnectServer method that SWbemLocator exposes lets you specify the credentials that you need to authenticate your WMI connection. However, the moniker syntax provides a powerful way to use one line of code to perform several steps.
The objects that the WMI scripting library provides let you use a consistent approach to mine WMI data. In my next column, I'll examine WMI scripting library objects that provide more functionality. In the meantime, I encourage you to take one of the two listings and modify the script to retrieve other Win32 classes. Need a hint? Besides changing the class name that the script passes to the InstancesOf method, you need to modify the For... Each loop body to match the methods and properties that the class you select provides. Have fun!