Downloads
20401.zip

Learn to construct strings that concisely describe WMI objects that you want to retrieve and manage

Windows Management Instrumentation (WMI) provides two distinct mechanisms you can use to connect to WMI and mine system information in your WMI scripts: the WMI Scripting Library's SWbemLocator object, and the WMI moniker, "winmgmts:". The moniker is considered more powerful because it lets you use just one line of code to concisely describe a WMI object or collection of WMI objects to retrieve and manage. However, with power comes the difficulty of constructing complex WMI moniker strings. Let's decipher the components you can use to construct WMI monikers and look at a few best practices for writing WMI scripts that use WMI monikers.

This column assumes a basic knowledge of WMI and WMI terminology. To get quickly up to speed on WMI, read the articles in "Related Articles in Previous Issues."

A Moniker Is ...
Before I dive into the individual components you can use to build WMI moniker strings, I should define exactly what a moniker is because it's an unfamiliar term to many systems administrators. The term moniker comes from the COM programming discipline. In simple terms, a moniker is a string, also called a display name, that provides location and identity information about an object that you want to instantiate in your script. From a pure COM point of view, a moniker is just another programmatic identifier (ProgID) that maps to a class identifier (CLSID) that in turn points to the DLL containing the target automation object. As with all automation objects you can instantiate in your scripts, all the WMI moniker registration information is conveniently stored in the registry's HKEY_CLASSES_ROOT hive.

A moniker's syntax is implementation specific. That is, the developers of an automation technology that implements monikers determine the syntax, structure, and behavior of any moniker the technology recognizes and responds to. Consider Microsoft Active Directory Service Interfaces (ADSI) and WMI, for example. Both technologies make use of monikers as a way for you to describe objects in your scripts. However, each technology uses a unique style and syntax. ADSI uses a moniker string that makes sense to a directory service. WMI uses a string that accommodates a wide range of system-related information. From a systems administrator's perspective, a moniker is simply a string that's passed to VBScript's GetObject function. The string's contents determine what's returned to the calling script, which in turn governs the context in which the moniker can be used in the script.

In WMI, you can specify a moniker that returns a reference to the WMI Scripting Library's SWbemServices object, which you can use to invoke one of SWbemServices' methods (e.g., ExecQuery, Get, InstancesOf). You can specify a moniker that returns a reference to an SWbemObjectSet representing a collection of WMI objects to manage. And you can create a moniker that returns a reference to a discrete SWbemObject. The fact that the WMI moniker syntax can retrieve all these object types gives you an idea of the power and flexibility monikers provide.

WMI Moniker Basics
WMI monikers can consist of three parts: one mandatory and two optional components. The mandatory component is the "winmgmts:" prefix. All WMI monikers must begin with "winmgmts:", as the following statement shows:

Set wmiServices = _
  GetObject("winmgmts:")

The moniker in this case is the string "winmgmts:" that's passed to VBScript's GetObject function. Although I used all lowercase letters to enter the string in this example, you can use whatever case you like. "WinMgmts:", "WINMGMTS:", and "winmgmts:" all produce the same result.

A moniker that consists of only the "winmgmts:" prefix is the most basic form of a WMI moniker. The result is always a reference to the WMI Scripting Library's SWbemServices object, which represents a connection to the WMI service on the local computer. Under the covers, the "winmgmts:" moniker maps to HKEY_ CLASSES_ROOT\WINMGMTS, which maps to HKEY_CLASSES_ROOT\CLSID\ \{172BDDF8-CEEA-11D1-8B05-00600806 D9B6\}, which in turn points to C:\winnt\system32\wbem\wbemdisp.dll, which is the DLL containing the WMI Scripting Library.

After you've created this reference, you can invoke one of SWbemServices' methods to dive deeper into the WMI Scripting Object Model, as the statements in Listing 1 show. This example uses the "winmgmts:" moniker to initialize a variable named wmiServices. WmiServices subsequently invokes the InstancesOf method that the SWbemServices object provides. Although this example is perfectly acceptable, you don't really need two lines of script to retrieve all Win32_LogicalDisk instances. You can just as easily perform the task with the one line of script that Listing 2 shows.

Listing 2 leverages the fact that the "winmgmts:" moniker can immediately invoke SWbemServices' InstancesOf method to return an SWbemServices object. Both examples produce identical results in the form of an SWbemObjectSet collection containing all instances of the Win32_LogicalDisk class on the local computer. I can call just as easily the SWbemServices ExecQuery method or any other method that the SWbemServices object provides. In fact, if the objective of my script is to simply enumerate and echo all Win32_LogicalDisk instances, I can get by with just the statements in Listing 3. If you understand the most basic WMI moniker's relationship with the WMI Scripting Library, you can begin to construct concise and powerful WMI statements.

WMI Security-Settings Component
The second and a sometimes-optional part of WMI monikers is the security-settings component, which lets you specify several different security settings for the WMI connection. The security settings you can control as part of the moniker string are

  • impersonation level, expressed as "winmgmts:\{impersonationLevel=Value\}"
  • authentication level, expressed as "winmgmts:\{authenticationLevel=Value\}"
  • authenticating authority, expressed as "winmgmts:\{authority=ntlmdomain:DomainName\}" or "winmgmts:\{authority=kerberos:DomainName\ServerName\}"
  • privileges to grant or deny, expressed as "winmgmts:\{(Security,!RemoteShutdown)\}"

The first two settings, impersonationLevel and authenticationLevel, aren't specific to WMI but rather to Distributed COM (DCOM). WMI uses DCOM to access the WMI infrastructure on remote computers. In the context of WMI, impersonation governs the degree to which your script lets a remote WMI service carry out tasks for you. DCOM supports four levels of impersonation: Anonymous, Identify, Impersonate, and Delegate.

Anonymous impersonation hides your credentials, and the Identify value permits a remote object to query your credentials; neither level lets the remote object impersonate your security context. WMI scripts that use one of these two settings to access remote computers will generally fail. The Impersonate value lets the remote WMI service use your security context to perform the requested operation. A remote WMI request that uses the Impersonate setting typically succeeds if your credentials have sufficient privileges to perform the intended operation. The Delegate value lets the remote WMI service pass your credentials to other objects and is generally considered a security risk.

Some confusion surrounds the impersonationLevel setting because WMI's default impersonation behavior varies according to the WMI version on the target computer. WMI versions earlier than version 1.5 use Identify as the default impersonationLevel setting. This setting forces WMI scripts that connect to remote computers to include impersonationLevel=Impersonate as part of any moniker string. In WMI 1.5 in Windows 2000, Microsoft changed the default impersonationLevel setting to Impersonate. You can use the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM\Scripting\Default Impersonation Level registry subkey to locate and manage this setting.

If your WMI scripts connect only to computers with WMI 1.5, you don't need to explicitly set impersonationLevel=Impersonate. However, if you omit it, scripts accessing computers with an earlier release of WMI fail. For backward and potentially future compatibility, you should always explicitly set impersonationLevel.

The authenticationLevel setting lets you request the level of DCOM authentication and privacy that a WMI connection should use. The seven permissible moniker settings are Default, None, Connect, Call, Pkt, PktIntegrity, and PktPrivacy. DCOM won't necessarily honor your requested setting. For example, local connections always use authenticationLevel=PktPrivacy.

The authority setting lets you specify the security package that WMI uses to authenticate your WMI connection. You can specify standard NT LAN Manager (NTLM) or Kerberos authentication. To use NTLM, specify authority=ntlmdomain:DomainName, where DomainName identifies a valid NTLM domain name. To use Kerberos, specify authority=kerberos:DomainName\ServerName. You can't include the authority setting in WMI monikers that access the local computer.

The final security setting lets you grant or revoke privileges as part of a WMI moniker string. For example, you might grant yourself the Security privilege so that you can successfully query the Win2K or Windows NT Security log. The privileges you can override are CreateToken, PrimaryToken, LockMemory, IncreaseQuota, MachineAccount, Tcb, Security, TakeOwnership, LoadDriver, SystemProfile, SystemTime, ProfileSingleProcess, IncreaseBasePriority, CreatePagefile, CreatePermanent, Backup, Restore, Shutdown, Debug, Audit, SystemEnvironment, ChangeNotify, RemoteShutdown, Udock, SyncAgent, and EnableDelegation. To grant a privilege, list the privilege name. To revoke a privilege, preface the privilege name with an exclamation point (!).

Listing 4 shows the general format you use when including security settings in WMI monikers. The security-settings component immediately follows the colon (:) in "winmgmts:" and is enclosed in braces. You must comma-delimit multiple settings, and you must further separate override privileges inside parentheses and comma-delimit them.

WMI Object-Path Component
The third component of WMI monikers is a WMI object path, and like the security-settings component, the object path component is optional. However, the object path provides a great deal of flexibility, including the ability to identify remote computers, so chances are good that you'll use WMI object paths. You use a WMI object path to uniquely identify one or more of the following target resources:

  • remote computer
  • WMI namespace
  • Common Information Model (CIM) class within a namespace
  • specific instances of a CIM class within a namespace

The format of the object-path component varies slightly depending on whether you also include some portion of the security-settings component. If you include security settings, the object path follows the security settings' closing brace and is separated from the security component by an exclamation point, as the statement in Listing 5 shows. If you omit security settings altogether, the object path follows the colon in "winmgmts:" without the exclamation point, as the statement in Listing 6 shows.

Notice that you format the object path hierarchically, beginning with the target computer name, followed by a WMI namespace, followed by a CIM class name, and ending with a key value. Although I included all the object-path subcomponents in the listings, you can specify only what you need to while observing the following constraints and guidelines:

  • WMI connects to the local computer if you don't supply a target computer name or if you provide a dot (.) as the computer name (e.g., "winmgmts://./ root/cimv2"). If you omit the target namespace, WMI accesses the default namespace that the HKEY_LOCAL_ MACHINE\SOFTWARE\Microsoft\ WBEM\Scripting\Default Namespace subkey defines. The default namespace for scripting is root\cimv2. You can use the Microsoft Management Console (MMC) WMI Control snap-in's Advanced tab to change this value.
  • You can't omit the target namespace in WMI monikers that specify a target computer name and CIM class name.
  • Values that you use to identify a specific instance of a class must correspond to a CIM class key. For example, the key for the Win32_LogicalDisk class is DeviceID. Thus, you must specify an appropriate value for the DeviceID property when identifying a specific instance of the Win32_LogicalDisk class. To determine CIM class keys, use wbemtest.exe or WMI CIM Studio, or view the Managed Object Format (MOF) file that contains the corresponding class definition.

WMI Moniker Best Practices
Here are a few key take-aways regarding the WMI moniker and its components:

  • Always explicitly set impersonationLevel. Don't rely on the Default Impersonation Level registry subkey.
  • Likewise, always explicitly identify the target namespace rather than relying on the Default Namespace registry subkey. If the default value changes and you don't realize it, the result isn't fun.
  • If your script mines data from multiple CIM classes, create one reference to an SWbemServices object and reuse the reference.
  • If you must supply a username and password, you can't use the WMI moniker. You must use the WMI Scripting Library's SWbemLocator object instead.

To learn more about the WMI moniker, visit the Microsoft Developer Network (MSDN) Online Library at http://msdn.microsoft.com/library/psdk/wmisdk/scintro_6tpv.htm and http://msdn.microsoft.com/library/psdk/wmisdk/hmmapp_2z8z.htm. You'll find useful information and numerous moniker examples to use in your scripts.

Related Articles in Previous Issues
You can obtain the following articles from Windows 2000 Magazine's Web site at http://www.win2000mag.com.

BOB WELLS
Scripting Solutions, "Windows Management Instrumentation: The Systems Administrator's Apprentice," August 2000, InstantDoc ID 9033
Scripting Solutions, "Windows Management Instrumentation: The Journey Begins," July 2000, InstantDoc ID 8959