Managing Windows Networks Using Scripts – Part 3: Understanding WMI

If you would like to read the other parts in this article series please go to:

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.


Get your copy of Windows Server Hacks!

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 WMI

WMI 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:

  • Windows – works on and for computers running Microsoft Windows
  • Management – can be used to manage these computers
  • Instrumentation – provides instruments for viewing and modifying what goes on under the hood with these computers

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 Namespaces

Just 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”)
Set colNamespaces = objWMIService.InstancesOf(“__NAMESPACE”)
For Each objNamespace In colNamespaces
            WScript.Echo objNamespace.Name
Next

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
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
SECURITY
RSOP
Cli
SecurityCenter
WMI
CIMV2
Policy
Microsoft
DEFAULT
directory
subscription

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
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
ms_409
Applications

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
On Error Resume Next
Dim strComputer
Dim strWMINamespace
Dim objWMIService
Dim colNamespaces
Dim objNamespace
strComputer = “.”
strWMINamespace = “\root\CIMV2”
Set objWMIService = GetObject(“winmgmts:\\” & strComputer & strWMINamespace)
Set colNamespaces = objWMIService.InstancesOf(“__NAMESPACE”)
For Each objNamespace In colNamespaces
            WScript.Echo objNamespace.Name
Next

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 Providers

Finding 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
On Error Resume Next
Dim strComputer
Dim strWMINamespace
Dim objWMIService
Dim colWin32Providers
Dim objWin32Provider
strComputer = “.”
strWMINamespace = “\root\CIMV2”
Set objWMIService = GetObject(“winmgmts:\\” & strComputer & strWMINamespace)
Set colWin32Providers = objWMIService.InstancesOf(“__Win32Provider”)
For Each objWin32Provider In colWin32Providers
            WScript.Echo objWin32Provider.Name
Next

And here’s the output from running this script on a Windows XP machine:

C:\scripts>cscript ShowProviders.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
Win32_WIN32_TSLOGONSETTING_Prov
MS_NT_EVENTLOG_PROVIDER
Win32_WIN32_TSENVIRONMENTSETTING_Prov
SCM Event Provider
ProviderSubSystem
VolumeChangeEvents
NamedJobObjectLimitSettingProv
HiPerfCooker_v1
WMIPingProvider
Microsoft WMI Forwarding Event Provider
Win32_WIN32_TSNETWORKADAPTERSETTING_Prov
SystemConfigurationChangeEvents
Win32_WIN32_TERMINALSERVICE_Prov
Win32_WIN32_TSREMOTECONTROLSETTING_Prov
Win32_WIN32_TSNETWORKADAPTERLISTSETTING_Prov
Win32_WIN32_COMPUTERSYSTEMWINDOWSPRODUCTACTIVATIONSETTING_Prov
Win32_WIN32_TSSESSIONDIRECTORY_Prov
CmdTriggerConsumer
Standard Non-COM Event Provider
SessionProvider
WBEMCORE
RouteEventProvider
WhqlProvider
Win32_WIN32_TSSESSIONSETTING_Prov
Win32_WIN32_TERMINALTERMINALSETTING_Prov
Win32_WIN32_TSCLIENTSETTING_Prov
Win32_WIN32_TERMINALSERVICESETTING_Prov
WMI Kernel Trace Event Provider
Win32_WIN32_PROXY_Prov
NamedJobObjectProv
MS_Shutdown_Event_Provider
SECRCW32
Win32ClockProvider
MS_Power_Management_Event_Provider
Win32_WIN32_WINDOWSPRODUCTACTIVATION_Prov
RouteProvider
Cimwin32A
Msft_ProviderSubSystem
Win32_WIN32_TERMINALSERVICETOSETTING_Prov
NamedJobObjectSecLimitSettingProv
Win32_WIN32_TSSESSIONDIRECTORYSETTING_Prov
Win32_WIN32_TSPERMISSIONSSETTING_Prov
Win32_WIN32_TSACCOUNT_Prov
Win32_WIN32_TERMINAL_Prov
MSIProv
DskQuotaProvider
NetDiagProv
Win32_WIN32_TSGENERALSETTING_Prov
CIMWin32
NamedJobObjectActgInfoProv
NT5_GenericPerfProvider_V1
WMI Self-Instrumentation Event Provider
MS_NT_EVENTLOG_EVENT_PROVIDER

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 Classes

Besides 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
On Error Resume Next
Dim strComputer
Dim strWMINamespace
Dim objWMIService
Dim colClasses
Dim objClass
strComputer = “.”
strWMINamespace = “\root\CIMV2”

Set objWMIService = GetObject(“winmgmts:\\” & strComputer & strWMINamespace)

Set colClasses = objWMIService.SubclassesOf()
For Each objClass In colClasses
            WScript.Echo objClass.Path_.Path
Next

And here’s just some of the output (there’s lots!) from running this script on Windows XP:

C:\scripts>cscript ShowClasses.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
\\XP\ROOT\CIMV2:__SystemClass
\\XP\ROOT\CIMV2:__thisNAMESPACE
\\XP\ROOT\CIMV2:__Provider
\\XP\ROOT\CIMV2:__Win32Provider
\\XP\ROOT\CIMV2:__IndicationRelated
\\XP\ROOT\CIMV2:__EventGenerator
\\XP\ROOT\CIMV2:__TimerInstruction
\\XP\ROOT\CIMV2:__IntervalTimerInstruction

\\XP\ROOT\CIMV2:MSFT_WMI_GenericNonCOMEvent
\\XP\ROOT\CIMV2:MSFT_WmiSelfEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_OperationEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_ComServerLoadOperationEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_InitializationOperationFailureEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_LoadOperationEvent
\\XP\ROOT\CIMV2:Msft_WmiProvider_OperationEvent_Pre
\\XP\ROOT\CIMV2:Msft_WmiProvider_DeleteClassAsyncEvent_Pre
\\XP\ROOT\CIMV2:Msft_WmiProvider_GetObjectAsyncEvent_Pre

\\XP\ROOT\CIMV2:Win32_ComputerSystemEvent
\\XP\ROOT\CIMV2:Win32_ComputerShutdownEvent
\\XP\ROOT\CIMV2:Win32_SystemTrace
\\XP\ROOT\CIMV2:Win32_ModuleTrace
\\XP\ROOT\CIMV2:Win32_ModuleLoadTrace
\\XP\ROOT\CIMV2:Win32_ThreadTrace
\\XP\ROOT\CIMV2:Win32_ThreadStartTrace
\\XP\ROOT\CIMV2:Win32_ThreadStopTrace
\\XP\ROOT\CIMV2:Win32_ProcessTrace
\\XP\ROOT\CIMV2:Win32_ProcessStartTrace
\\XP\ROOT\CIMV2:Win32_ProcessStopTrace

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 WMI

Let’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
On Error Resume Next
Dim strComputer
Dim strWMINamespace
Dim strWMIQuery
Dim objWMIService
Dim colItems
Dim objItem
strComputer = “.”
strWMINamespace = “\root\CIMV2”
strWMIQuery = “SELECT * FROM Win32_TimeZone”
Set objWMIService = GetObject(“winmgmts:\\” & strComputer & strWMINamespace)
Set colItems = objWMIService.ExecQuery(strWMIQuery)
For Each objItem In colItems
            WScript.Echo objItem.Caption
Next

And here’s the result of running this script:

C:\scripts>cscript DisplayTimeZone.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
(GMT-06:00) Central Time (US & Canada)

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 Exercise

We’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.

If you would like to read the other parts in this article series please go to:

About The Author

Leave a Comment

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Scroll to Top