Simple Uses of WMI

Windows Management Instrumentation (WMI) is a tool that lets you communicate with, interact with, and automate devices on your network. WMI will be an important part of your scripting arsenal because the solutions you develop with WMI will take less time to implement than solutions you develop with older tools, such as the tools in the various Windows resource kits. In some cases, you need just two or three lines of script to implement a solution with WMI.

WMI is Microsoft's desired access mechanism that will ultimately replace all others, so learning to use WMI is a good idea. Thus, in this column, I present several examples of how to use WMI to access services and a variety of other items. If you're unfamiliar with WMI's basic architecture and terminology, check out Bob Wells' Scripting Solutions column in the July and August 2000 issues of Windows 2000 Magazine (http://www.win2000 He does a great job covering the basics of WMI. In addition, the Web-exclusive sidebar "Helpful WMI Documentation" on the Win32 Scripting Journal Web site (http://www points out good WMI resources within the Microsoft Developer Network (MSDN) Online Library that you can access. For information about how you can get WMI working on your system, see the sidebar "How to Enable WMI on Your Computer."

Accessing Services
You can use WMI to access services in many ways, depending on what you want to do and how you want to do it. If you just want to read data from a service (e.g., printer, Windows NT service, event log) on a computer and you don't want to authenticate with credentials that differ from those you logged on with, you can use WMI's SWbemServices object and a namespace to connect. For example, Listing 1 contains a script that connects to the local computer on which you run the script and displays all the services that are running on that computer. This script is similar to one that you might use to connect to Win2K's Active Directory (AD) to enumerate objects of the User or Computer class. In this case, however, you're connecting to WMI and enumerating objects of the Win32_Service class.

In layman's terms, here's how Listing 1 works: The script connects to the default WMI namespace, creates a collection containing the computer's Win32 services, walks through those services to retrieve each service's description, and adds each description to a text string. After the script adds the last description, it displays the text string. Figure 1 shows an example of the script's output.

Here's a more detailed explanation of how the script works: To connect to the default WMI namespace, the script uses VBScript's GetObject function with WMI's programmatic identifier (ProgID) WinMgmts://. After GetObject succeeds, WMI points to the SWbemServices object, which lets the script use the methods and properties of several WMI interfaces. In this case, you want a list of all the Win32 services, so the script uses the SWbemServices::InstancesOf method to return a collection of all the object instances of the Win32_Service class and assigns that collection to the wmiWin32Services variable. The script then uses a For Each...Next statement to iterate through each service (wmiWin32Service) in wmiWin32Services. For each service, the script uses the Win32_ Service::Description property to retrieve that service's description and appends that description to a text string (strText). Finally, the script applies Windows Script Host's (WSH's) Echo method to display the results in a message box.

You can easily adapt Listing 1 to retrieve and enumerate other classes. For example, to retrieve and enumerate a computer's printers instead of Win32 services, you need to make only these changes:

  • Change the variables' names to fit the particular application. In this case, change wmiWin32Service to wmiWin32Printer and change wmiWin32Services to wmiWin32Printers.
  • Change the class. In this case, change Win32_Service to Win32_Printer.
  • Change the property. In this case, change wmiWin32Service.Description to wmiWin32Printer.Caption.

Listing 2 contains the adapted script.

Both Listings 1 and 2 connect to the local computer. If you want to connect to another computer, you simply need to append the name of the computer you want to access to the end of the ProgID (e.g., WinMgmts://Server1, Win Mgmts://Bob). You can even adapt the scripts so that an input box prompts you for the computer you want to access. You just replace the code at callout A in Listing 1 or Listing 2 with the code at callout A in Listing 3 and add strComputer to the Dim statement. The first line of code at callout A in Listing 3 creates a standard input box, which receives either a blank string or a valid computer name. If the string is blank, GetObject works on the local machine as before; otherwise, GetObject binds to the specified machine.

Accessing Various Items
If you want to retrieve and enumerate many different items on any computer on your network, you can use the script in Listing 3. After this script prompts you to specify the computer you want to access, the script retrieves and enumerates the specified computer's service, printer, processor, and process descriptions. Because this script displays so many descriptions, it outputs its results to an HTML file within a dialog box rather than a standard message box. Figure 2 shows an example of this dialog box. The object that creates it is the WshKit::DialogBox object, which is part of the library in Dino Esposito's Windows Script Host Programmer's Reference (Wrox Press, 1999). You don't have to buy the book to download the library, but I encourage you to get it because it's one of the best WSH reference books on the market. Thus, before you can run the script in Listing 3, you need to perform two tasks:

  1. Download and install Esposito's library. You can download the library for free from consumer/store/download.asp?isbn =1861002653. You need to install the library on the computer on which you'll run the script. (If you plan to run the script on client A but want to query clients A, B, C, and D, you need to install the library only on A.)
  2. Download and install the template HTML file. The template results .htm contains a scrollable text field called results that the script adds data to. You can download this template from the Code Library on the Win32 Scripting Journal Web site and modify it as necessary. This template needs to be in the same location as the script.

After you finish these two tasks, you can run the script in Listing 3 without modification. The script uses the SWbemServices::InstancesOf method to return collections of the object instances of the Win32_Service, Win32_ Printer, Win32_Processor, and Win32_ Process classes. Rather than having a separate set variables for each type of object (e.g., wmiWin32Service and wmiWin32Services for the Win32_ Service class objects, wmiWin32Printer and wmiWin32Printers for the Win32_ Printer class objects), the script uses the generic variables wmiWin32Object and wmiWin32Objects for all the object types.

After the script retrieves all the descriptions, it uses the CreateObject function to instantiate the WshKit:: DialogBox object, as the code at callout B in Listing 3 shows. Using results .htm as a template, the script creates the dialog box. The script then sets the value of results to strText with the SetItemValue method. After resizing the window with the Move method, the script uses the Show method to display the dialog box.

Only the Beginning
These three scripts hint at what you can accomplish with WMI. Next month, I'll delve further into how you can use WMI to accomplish administrative tasks. Until then, you can check out the Web-exclusive script, OSInfo .wsf, that I've posted in the Code Library on the Win32 Scripting Journal Web site. This script is similar to that in Listing 3, except that OSInfo.wsf retrieves data about the OS installed on the specified computer instead of its services. The script uses the Win32_ ComputerSystem class, which represents computer systems operating in a Win32 environment. The script retrieves and displays only a few of the many properties of this class. To run this script, you need to have the results .htm HTML template and Esposito's library in place.