News

Managing Windows networks using scripts Part 3: Understanding WMI

Mitch Tulloch

PREVIOUSLY: Cleaning up our script

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.

Our

    Requires Free Membership to View

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_WmiP