| Practical Scripting Part 3: Understanding WMI |
|
|
|
|
In the first two articles of this series we saw how to change the IP address of a network adapter on a Windows computer using VBScript. Along the way we learned many of the basic concepts of Windows scripting such as classes, objects, properties, methods, and different types of variables including string variables, integer variables, arrays and collections. We also learned some of the basics of writing a good script such as defining variables, implementing error handling, accepting user input, displaying confirmation output, and documenting your script by adding comments. Our final script worked as expected, but there may be some aspects of it you still find mysterious. For example, take a look at this particular line: Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") In my first article, I made the following comment concerning this particular line: "This connects you to the root\cimv2 namespace on the local computer by defining an object named objWMIService and setting it equal to the handle returned by the GetObject method." What on earth does that mean? What's WMI and how does it work? And why is it important to learn about if you want to learn how to write scripts to administer Windows computers? Understanding WMIWMI has been around since the days of Windows 98 and earlier, only back then it was called something different: Web-Based Enterprise Management (WBEM). WBEM was a technology developed jointly by Microsoft, Cisco, Intel, Compaq and BMC Software to make it easier to manage desktop and server systems in enterprise environments. WMI provides a model for how to represent, store and query configuration and status information and other operational aspects of Windows computers. Developers can use WMI to write scripts or managed code to view and modify configuration settings on Windows computers, to view the status of Windows applications and services, and do a whole lot of other things useful to administrators who deploy, maintain and troubleshoot Windows-based networks. In other words, WMI stands for:
A good analogy is to think of a Windows computer as a car and WMI as the electronics (instrumentation) that enables your dashboard to display your speed, engine temperature, RPMs, and so on. These dashboard controls aren't themselves WMI--you still have to figure out a way to get the info out of the electronics and present it in a readable form. Writing VBScripts that use WMI is therefore like creating dashboard display elements that can hook into the instrumentation under your car's hood and tell you what you want to know and control what your engine is doing. In other words, Windows ships with all this instrumentation built into it via WMI--you just need to figure out how to get at it so you can do something useful with it like change your IP address, view your time zone, reboot a remote machine, display a list of installed hotfixes--whatever. WMI NamespacesJust about anything--well, not quite. Actually finding out whether WMI can do something in particular takes a bit of patience and understanding. Let's start by considering WMI namespaces. In WMI terminology, a namespace is a kind of logical database of classes and their instances. Here's a simple script called ShowNamespaces.vbs that enumerates all WMI namespaces under the root namespace: Set objWMIService = GetObject("winmgmts:\\.\root") Here's the result of running this script on a Windows XP machine: C:\scripts>cscript ShowNamespaces.vbs Microsoft (R) Windows Script Host Version 5.6 Each of these namespaces is a possible source which you can query for information concerning the status or configuration of some aspect of a Windows computer (and often modify that configuration as well). These namespaces are organized hierarchically like the folders on a hard drive. For example, we can display all the namespaces under the root\CIMV2 namespace by modifying the first line of our script as follows: Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2") When you run this modified script, the output looks like this: C:\scripts>cscript ShowNamespaces.vbs In fact, root\CIMV2 is the default WMI namespace on Windows machines. What this means is that if you don't specify a namespace to connect to in the first line of this script, WMI will automatically connect to the root\CIMV2 namespace by default. So if we change the first line to this: Set objWMIService = GetObject("winmgmts:\\") we get the same results as above. Note that we've also left out the period in winmgmts:\\.\root\CIMV2. If you remember from our first article, this period represented the local computer and by default WMI assumes you want to work with the local computer which means you can leave out the period if you want to. Best practices for scripting however is to use variables (and define them) so here's a more generalized script we can use for displaying WMI namespaces: Option Explicit Why go to all this trouble? The main reason is flexibility! For example, if we need to run the script against a remote computer we can change the value of strComputer to the IP address of the remote machine. Or if we need to display a different portion of the namespace, we could add a few lines to our script to accept user input for the strWMINamespace variable. WMI ProvidersFinding the right namespace is just the first challenge (though much of the time connecting to the default namespace will suffice). You also have to access the right provider in order to retrieve or update data on the system you are targeting. Here's a script called ShowProviders.vbs that displays all the WMI providers for the root\CIMV2 namespace: Option Explicit And here's the output from running this script on a Windows XP machine: C:\scripts>cscript ShowProviders.vbs Looks a bit overwhelming, doesn't it? Using this list of providers however, you can easily search MSDN for more information concerning a particular provider and find what methods it supports, that is, what you can do with the provider using WMI. WMI ClassesBesides namespaces and providers, you also need to understand WMI classes if you want to leverage the power of WMI to script Windows administration tasks. A class is a kind of template for a type of object you can manage using WMI. For example, the class named Win32_LogicalDisk is a template for logical disks on Windows machines, and WMI uses this class to generate one instance of Win32_LogicalDisk for each installed disk. Here's a script called ShowClasses.vbs that displays all the classes (potentially manageable objects) for the root\CIMV2 namespace: Option Explicit And here's just some of the output (there's lots!) from running this script on Windows XP: C:\scripts>cscript ShowClasses.vbs Again, this all looks a bit overwhelming, but using this list of classes you can search MSDN for more information concerning a particular WMI class to find what properties and methods are associated with. Using WMILet's make some use of what we've learned above. One of the classes that the script above displays is Win32_TimeZone, and let's use this to display the time zone that's configured on the computer. First we need to find out more about this class, and searching for "Win32_TimeZone class" brings up this page on MSDN. On this page we can find information about the properties and methods that this class supports (though actually this particular class only has properties and no methods) and using this information we should be able to write the script we want. A little experimenting shows that it's the Caption property that we want to display as this is the most "human-readable" form of time zone information stored on the machine. Here's the script named DisplayTimeZone.vbs that we'll use to query WMI for this information and display it: Option Explicit And here's the result of running this script: C:\scripts>cscript DisplayTimeZone.vbs Let's see how this script works. First, you can see a lot of it is based on our previous scripts above. In other words, we begin by connecting WMI using the following statement: Set objWMIService = GetObject("winmgmts:\\" & strComputer & strWMINamespace) The next statement however is new: Set colItems = objWMIService.ExecQuery(strWMIQuery) What we're doing here is executing a query against WMI to gather some information from it. The query was defined earlier using the following statement: strWMIQuery = "SELECT * FROM Win32_TimeZone" This SQL-type SELECT statement basically returns everything (the asterisk) that the Win32_TimeZone provider has to offer us and stores the results in a collection named colItems. Then we loop through each item in this collection (there's only one item returned by the query) and display the Caption property of this item, which is the following text string: (GMT-06:00) Central Time (US & Canada) Try This ExerciseWe'll dig deeper into WMI scripting in future articles of this series, but for now let's try a little exercise. Copy the contents of the DisplayTimeZone.vbs script above into Notepad (make sure Word Wrap is turned off) and save it as PageFile.vbs. Now change one line in the script (actually only a small portion of a line) so that when the script is run it displays the path and name of your system's pagefile instead of its time zone. Here's a hint: search MSDN for info about the Win32_PageFile class. I'll give you the answer to this exercise in the next article in this series. |
| < Prev | Next > |
|---|



