Network Administration/WMI

Network Administration WMI

Overview

Gathering system information is a never-ending task for today's IT professionals.

The traditional method of querying Windows system-related information is calling a Windows API routine. This method is inconsistent and may not work over all Windows platforms, and an API for Windows 2000/XP may have a different interface than one for Windows 9x or NT. In addition, such APIs are not directly callable through scripting languages such as WSH, so a wrapper object must be written to encapsulate the logic.

An effort has been made to address the problem of adhering to a consistent standard to query system information that is known as Web-Based Enterprise Management (WBEM). WBEM is an attempt to provide a standard way of representing and accessing enterprise system information. WBEM is an industry standard that was implemented by the Desktop Management Task Force (DMTF), an industry standards organization.

Windows Management Instrumentation (WMI) is Microsoft's implementation of WBEM. WMI is an extensible architecture, which allows for additional functionality to be implemented within the WMI framework. Functionality is implemented through providers, and additional providers can be developed to interface new software. For example, Exchange 2000 includes WMI providers that allow for monitoring and administering Exchange 2000 services.

Using WMI you can query a wide variety of system information, such as computer memory, BIOS, network adapters, drive controllers, video, and printer configurations. It also provides the ability to query Event Viewer, SNMP, registry, and performance counter information.

WMI exposes system information through object classes. A class can represent a system element, such as a hard drive or network adapter. Information is exposed through properties, while operations can be performed against classes by executing methods. Methods perform class-related operations, which might be to set an IP address for a network adapter object or clear an event log for an event log object. The default installation of WMI contains hundreds of classes.

Classes are organized in namespaces. A namespace represents a collection of logically grouped classes. By default, there is a root namespace and additional namespaces reside below the root, similar to a directory structure.

To use a WMI object you need to know the object's path. The path consists of a combination of the computer name, namespace, and object class:

\ComputerNamespace:Class

The computer name must be prefixed by two backslashes (\) and followed by a single backslash () as separator between the namespace and computer name. The ability to specify a remote computer name is one of the most exciting aspects of WMI, because it allows operations to be performed against remote computers. If the computer name is omitted from the path, the local computer is assumed.

The namespace is where to find the WMI object class you want to use. Namespaces can have multiple levels and start from a root level, which contains additional namespace levels. The namespace levels are separated using the backslash character (). One of the most used namespaces is the Common Information Model Version 2 (CIMV2) namespace, which resides below the root level. The path to this namespace is rootcimv2.

The final part of the path is the class object. The class object is appended to the end of the path and separated from the namespace by a colon (:).

The full path to the Win32_ComputerSystem object that resides in the Cimv2 namespace under Root is RootCimv2:Win32_ComputerSystem. If you attempt to create an instance of this object on the remote computer Thor, you prefix the path with the computer name: \ThorRootCimv2:Win32_ComputerSystem.

Most important, WMI is accessible through a COM interface, allowing all information and operations to be accessed from WSH. WMI comes installed with Windows 2000/XP and can be installed on Windows NT and Windows 9x.

This chapter concentrates on how to access information and perform operations through WMI classes, but it also covers how to use available tools to navigate the WMI classes and namespaces.

  Note 

For more information, read the articles "WMI: A Simple, Powerful Tool for Scripting Windows Management" (http://msdn.microsoft.com/msdnmag/issues/0400/wmi/wmi.asp), "Managing Windows with WMI" (http://msdn.microsoft.com/library/default.asp?URL=/library/techart/mngwmi.htm), "WMI: Administering Windows and Applications across Your Enterprise" (http://msdn.microsoft.com/msdnmag/issues/0500/wmiover/wmiover.asp), "Microsoft Windows Management Instrumentation Scripting" (http://msdn.microsoft.com/library/backgrnd/html/wmiscript.htm), "Administrating Windows through WSH" (http://www.microsoft.com/mind/defaulttop.asp?page=/mind/1199/adminwsh/adminwsh.htm&nav=/mind/1199/inthisissuecolumns1199.htm), and "WMI SDK" (http://msdn.microsoft.com/downloads/default.asp?URL=/code/sample.asp?url=/msdn-files/027/001/566/msdncompositedoc.xml).

Accessing Information about a Computer

Problem

You want to access general computer information such as operating system (OS) details and system information.

Solution

Create an instance of the Win32_ComputerSystem WMI class to get computer details:

Dim objService, objWMIObject, objWMIObjects

'create an instance of a Services object for namespace rootcimv2
Set objServices = _
 GetObject("winmgmts:{impersonationLevel=impersonate}!rootcimv2")

'create a collection of Win32_ComputerSystem class objects
Set objWMIObjects = objServices.InstancesOf("Win32_ComputerSystem")

'enumerate collection.. there will only be one object, the local computer
For Each objWMIObject In objWMIObjects
 'display some information from the class
 WScript.Echo "Computer description:" & objWMIObject.Description
 WScript.Echo "Physical memory:" & objWMIObject.TotalPhysicalMemory
 WScript.Echo "Manufacturer:" & objWMIObject.Manufacturer
Next

Discussion

To get references to WMI objects, you must create a WMI Services object for the namespace you want to query for information and/or perform operations against.

There are two ways to create a WMI Services object. One way is to create a SwbemLocator object and connect to a local or remote server:

Set objLocator = CreateObject("WbemScripting.SWbemLocator")

Once you have an instance of the SwbemLocator object, use its ConnectServer method to connect to a WMI service for a specified computer. The syntax is as follows:

Set objSrv = objLoc.ConnectServer([strSrvr], [strNameSpace], [strUser],
[strPass])

Table 10-1 lists the ConnectServer method's arguments.

Table 10-1: ConnectServer Method Arguments

PARAMETER

DESCRIPTION

strSrvr

Name of the computer to connect to. If not specified, the local computer that code is executed on is assumed. Even though the name implies a server, it can be any computer with WMI installed.

strNameSpace

WMI namespace to access. If omitted, the default namespace configured on the machine is used, which is generally root CIMV2. The default namespace is determined by the HKEY_LOCAL_MACHINESoftwareMicrosoftWBEMScriptingDefault Namespace registry key.

strUser

Account name to use to authenticate against the service. Use only if a level of authentication is required that is not provided by the current logged-on user. The user name can be specified as username or domainusername. If omitted, the security credentials of the current logged-on user are used.

strPass

Password required to authenticate the strUser account.

All parameters for the ConnectServer method are optional. If you omit all parameters, the Locator object will attempt to connect to the default namespace on the local machine using the authentication of the logged-on user:

'connect to local computer
Set objLocator = CreateObject("WbemScripting.SWbemLocator")

 Set objServices = objLocator.ConnectServer()

An error will occur if the locator is unable to connect to the specified computer.

Before you perform any operations, it is important to make sure the level of security provided by the Service object is sufficient. Access to WMI objects is determined by the security level of the caller. This is determined by the impersonation level.

The impersonation level is determined by the ImpersonationLevel property of the Services object's .Security_ property, and it can have any of the values listed in Table 10-2.

Table 10-2: Impersonation Security Levels

IMPERSONATION LEVEL

VALUE

MEANING

Anonymous

1

Hides information about the caller

Identify

2

Allows objects to query the identification of the caller

Impersonate

3

Uses the security credentials of the caller

Delegate

4

Allows objects to use the security access of the caller

Using an impersonation level that is too low (Anonymous or Identify) might prevent access to WMI objects. Using the Delegate level allows objects created by the user to create instances of other objects using the security level of the caller and should not be used unless there's a specific need for it. The Impersonate level is the recommended level.

'connect to WMI services for the default namespace on the local computer
Set objLocator = CreateObject("WbemScripting.SWbemLocator")

Set objService = objLocator.ConnectServer()

'set security level for service object to 3, impersonate
objService.Security_.ImpersonationLevel = 3

If the impersonation level is not specified, it is set to the default value, which is determined by the registry value stored under HKEY_LOCAL_MACHINESoftwareMicrosoftWBEMScripting Default Impersonation Level. This value is set to 3, Impersonate, during the WMI installation.

Another way to create a WMI Services object is to use the GetObject function to bind to a Service object. GetObject requires that you pass a moniker. A moniker is a connection string that contains the path to the WMI namespace you want to access together with optional security information.

The following snippet returns a reference to a Services object for the WMI namespace rootcimv2 using GetObject:

'get a reference to a WMI service object
Dim objServices
Set objServices = GetObject("winmgmts:rootcimv2")

Note the path to the service namespace is prefixed by winmgmts (Windows Management). Any references to WMI objects using GetObject must be prefixed by winmgmts so Windows can determine how to create the object. The moniker string is not case-sensitive.

If the namespace is omitted in the moniker, the default namespace is used, similar to the ConnectServer method. As a result, the following code statement is equivalent to the previous example, assuming rootcimv2 is the default namespace:

'get a reference to a WMI services object for the default namespace
Set objService = GetObject("winmgmts:")

To specify security within the moniker, include the setting(s) enclosed within braces ({}). An exclamation point (!) separates the security settings and object path:

Set objService = _
 GetObject("winmgmts:{impersonationLevel=impersonate}!rootcimv2")

In this example, impersonationLevel is set to impersonate. The impersonation level can be set to any of the levels listed earlier in this section. If the impersonation level is omitted, the default impersonation level for the computer is used.

  Note 

WMI provides additional connection information to be set when connecting to a namespace, such as system locale and connection privileges. Coverage of this information is beyond the scope of this chapter.

You can now use the WMI Services object to create instances of specific WMI classes. Use the Services object's InstancesOf method to create a set of one or more instances of a class:

Set objWMIObjects = objServices.InstancesOf(strClassName)

The strClassName parameter is the name of the WMI class to create an instance of.

The InstancesOf method returns a collection of one or more WMI objects. The Solution script creates an instance of a Win32_OperatingSystem class and displays a number of associated OS properties for each object in the collection.

You can reference individual WMI objects from the collection by providing an index value. The index is a key associated with the object class.

Unlike collections found in other object models, you cannot reference instances of a class by an index number.

In the Solution script, an instance of the Win32_ComputerSystem class is created and enumerated. The Win32_ComputerSystem class exposes information related to a specific computer, so it will never return more than one instance.

The Win32_ComputerSystem class is keyed on a Name property, which is the name assigned to the computer. To get a reference to the Win32_ComputerSystem object on the computer Odin where the script is running, use the following code:

Set objService = _
 GetObject("winmgmts:{impersonationLevel=impersonate}!rootcimv2")

'create an instance of the Win32_ComputerSystem class
Set objWMIObjects = objService.InstancesOf("Win32_ComputerSystem")
'get a reference to the local computer Odin
Set objWMIObject = objWMIObjects("Win32_ComputerSystem.Name=" _
 & "'Odin'")

Even though you are getting a reference to the local computer called Odin, you must specify the name of the computer because it is the key property for the class. Specifying a remote computer name will result in an error.

If you want to get a reference to the Win32_ComputerSystem class on the remote machine Thor (a remote call) you have to specify the name of the remote computer you are trying to reference as part of the namespace path when creating a Services object:

'get a reference to a WMI service on remote computer Thor
Set objService = _
 GetObject("winmgmts:{impersonationLevel=impersonate}!\Thor
ootcimv2")

'create an instance of the Win32_ComputerSystem class
Set objWMIObjects = objService.InstancesOf("Win32_ComputerSystem")
'get a reference to the computer object Thor
Set objWMIObject = objWMIObjects("Win32_ComputerSystem.Name=" _
 & "'Thor'")

Prefixing the WMI path with the computer name attempts to connect to the remote computer Thor. Any remote computer you are connecting to using WMI must also have a copy of WMI installed. You must also have appropriate security access to the computer you are accessing.

Individual instances of WMI object classes can be created using GetObject. This results in less code than first creating a Services object and enumerating individual instances.

To create a specific instance of a class, append a colon (:) followed by the key to the object you want to reference:

Set objWMIObject = GetObject(_
 "winmgmts:{impersonationLevel=impersonate}!rootcimv2:" & _
 "Win32_ComputerSystem.Name='Odin'")

In the previous sample an instance of the Win32_ComputerSystem class is created for the computer Odin.

While the method of referring to individual instances of WMI objects results in less code, it is better to create a single instance of a Services object if you intend to create more than one instance of any given class within a namespace.

Not all properties exposed through Win32_ComputerSystem will return values. This depends upon the underlying operating system. Some operating systems expose more information through the providers than others.

To determine information about WMI classes, such as property and index values, you can use the WBEM CIM Studio that comes with the WBEM/WMI SDK. The WMI CIM Studio only runs under Windows NT/2000/XP.

To start the WMI CIM Studio, perform the following steps:

  1. Select Start menu > WMI SDK > WMI CIM Studio.
  2. The "Connect to namespace" dialog box appears, as shown in Figure 10-1.

    click to expand
    Figure 10-1: Connect to namespace

Clicking the button enables you to connect to a remote computer or use alternative user authentication.

Once you have selected a namespace and optionally a remote computer, you can connect to the WMI service. The WMI CIM Studio will enumerate all classes within the namespace. Figure 10-2 shows the WMI CIM Studio when it's connected to the rootCIMV2 namespace.

click to expand
Figure 10-2: WMI CIM Studio

You can now browse the classes within the namespace and inspect the properties exposed by any given class.

A useful feature of the WMI CIM Studio is the capability to create instances of any given class. This allows for the properties of the created objects to be browsed.

To create instance(s) of a class, select the class from the WMI CIM Studio and select the Instances button.

Figure 10-3 shows the results of creating an instance of the Win32_ComputerSystem class from the WMI CIM Studio.

click to expand
Figure 10-3: Win32_ComputerSystem class

  Note 

Some classes cannot be instantiated from the WMI CIM Studio. Other classes may return more instances of objects than can be displayed in the WMI CIM Studio.

Querying computer-related information, such hardware and user information, is a common operation. WMI exposes this information through a number of classes, such as Win32_OperatingSystem, Win32_BIOS, Win32_Processor, Win32_LogicalMemoryConfiguration, and Win32_ComputerSystem.

Instead of creating instances of these classes each time you require this information, you can use a WSC scripting component to create a reusable generic object that exposes this information.

The following two code listings show the code for such an object. The first segment contains the code for a SysInfo class. This contains the logic to create instances of WMI objects.

The second segment contains the code for the actual WSC object. The object uses the code from the SysInfo class to generate the system information, which is then encapsulated and exposed in the component.

'Sysinfo class
Option Explicit
Const Impersonate = 3
Class SysInfo

Dim objService, objComputer, objProcessor
Dim objLocator, objOS, objMemory, objBIOS

Private Sub Class_Terminate()
 Set objLocator = Nothing
 Set objService = Nothing
 Set objOS = Nothing
 Set objMemory = Nothing
 Set objBIOS = Nothing
 Set objComputer = Nothing
 Set objProcessor = Nothing
End Sub

Private Sub Class_Initialize()

 Set objLocator = CreateObject("WbemScripting.SWbemLocator")
 'connect to specified machine
 Set objService = objLocator.ConnectServer()
 objService.Security_.ImpersonationLevel = Impersonate

 Set objOS = GetReference("Win32_OperatingSystem")
 Set objMemory = GetReference("Win32_LogicalMemoryConfiguration")
 Set objBIOS = GetReference("Win32_BIOS")
 Set objComputer = GetReference("Win32_ComputerSystem")
 Set objProcessor = GetReference("Win32_Processor")
 End Sub

Private Function GetReference(strObjectName)
 Dim objInstance, objObjectSet

 'get reference to object
 Set objObjectSet = objService.InstancesOf(strObjectName)
 'loop through and get reference to specified
 For Each objInstance In objObjectSet
 Set GetReference = objInstance
 Next

End Function

Public Property Get BIOSObject()
 Set BIOSObject = objBIOS
End Property

Public Property Get ProcessorObject()
 Set ProcessorObject = objProcessor
End Property

Public Property Get MemoryObject()
 Set MemoryObject = objMemory
End Property

Public Property Get OSObject()
 Set OSObject = objOS
End Property

End Class






 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 




The advantage of using a class object is the Class_Initialize and Class_Terminate subroutines. The Class_Initialize routine is executed upon creation of the class, while the Class_Terminate method executes upon termination of the class. This ensures that a cleanup of object resources is performed and no separate methods need to be called to initialize the objects before performing operations.

To use the object, register the SysInfo.wsc scripting component file by either right-clicking the file from Explorer and selecting register or by using the regsvr32.exe program from the command line:

regsvr32.exe SysInfo.wsc

The object is demonstrated in the following snippet:

Dim objSysInfo
Set objSysInfo = CreateObject("ENTWSH.SysInfo")
WScript.Echo "BIOS Version:" & objSysInfo.BIOSVersion
 WScript.Echo "CPU:" & objSysInfo.CPU
 WScript.Echo "Memory:" & objSysInfo.Memory
 WScript.Echo "O/S Version:" & objSysInfo.OS
 WScript.Echo "O/S Registered User:" & objSysInfo.RegisteredUser
 WScript.Echo "O/S Serial #:" & objSysInfo.SerialNumber
 WScript.Echo "Virtual Memory:" & objSysInfo.VirtualMemory

See Also

See the following topics from the WMI SDK: "Object Creation and Monikers" and "Connecting To WMI." For more information, read the MSDN Library articles "Win32_OperatingSystem" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32os4_0h7x.asp), "Win32_ComputerSystem" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32os2_5ijx.asp), "Win32_LogicalMemoryConfiguration"(http://msdn.microsoft.com/library/en-us/wmisdk/r_32os3_4ram.asp), "Win32_Processor" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32hard6_4bsi.asp), "Windows Management Instrumentation: Administering Windows and Applications across Your Enterprise" (http://msdn.microsoft.com/msdnmag/issues/0500/wmiover/wmiover.asp), and "Win32_BIOS" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32hard1_9tpv.asp).

Determining the Role of a Computer

Problem

You want to determine if a computer is a network primary domain controller.

Solution

The Win32_ComputerSystem class contains computer-related information properties, such as make and model. It also exposes a Roles property, which is an array of values listing what roles a computer performs. Roles include the OS type as well as services the computer may run, such as PDC, BDC, SQL, and browse master.

The ispdc.vbs script creates an instance of the Win32_ComputerSystem class for the local computer and checks if the Roles property contains Primary_Domain_Controller.

'ISPDC.VBS
'checks if computer is a Primary Domain Controller (PDC)
Dim objWMIObject, objServices, objNetwork, nF, bFound, objRole
Set objNetwork = CreateObject("WScript.Network")
'get an instance of the Win32_ComputerSystem for the local computer
Set objWMIObject = _
 GetObject("winmgmts:{impersonationLevel=impersonate}" & _
 "!Win32_ComputerSystem='" & objNetwork.ComputerName & "'")
bFound = False

'check if Roles property is Empty array
If Not IsNull(objWMIObject.roles) Then
 'loop through roles array and check if it contains any occurrence
'of Primary_Domain_Controller
For nF = LBound(objWMIObject.roles) To UBound(objWMIObject.roles)
 For Each objRole In objWMIObject.Roles
 If objRole = "Primary_Domain_Controller" Then
 bFound = True
 Exit For
 End If
 Next
End If

'if PDC then return -1, otherwise 0
If bFound Then WScript.Quit -1
WScript.Quit 0

The script can be used from a batch file to determine if the computer the script is executing on is a PDC. The WScript.Quit method sets the ERRORLEVEL environment variable to -1 within the script if a PDC is detected and 0 if it is not a PDC. This can be

Rem Execute the ispdc.vbs script
cscript ispdc.vbs
Rem Check if ERRORLEVEL was set to -1, which indicates a PDC
If ERRORLEVEL = -1 Goto Exit
Echo This is not a PDC
:Exit

Discussion

To create an instance of the Win32_ComputerSystem class for your local computer, reference the class using the key property. The key for the Win32_ComputerSystem class is the computer name. The following code gets a reference to the computer Thor:

Const WMIConnect = "winmgmts:{impersonationLevel=impersonate}!:"
Dim objWMIObject
Set objWMIObject = _
GetObject("WMIConnect & Win32_ComputerSystem.Name='Thor'")

If you intend to perform multiple WMI operations against a local or remote computer, it is more efficient to first get a reference to the WMI service and then create instances of the WMI class from that service:

Dim objWMIObject, objServices

'get an instance to the Services object for the default namespace on '
'remote computer Odin
Set objServices = _
 GetObject("winmgmts:{impersonationLevel=impersonate}!\odin")
'get an instance of the WMI class Win32_ComputerSystem for computer Odin
 Set objWMIObject = _
 objServices.Get("Win32_ComputerSystem='odin'")

'output some info about the computer
WScript.Echo "Owner: "& objWMIObject.PrimaryOwnerName
WScript.Echo "Startup delay: "& objWMIObject.SystemStartupDelay

The Win32_ComputerSystem object's Roles property is an array of values that identify what operations the computer can perform. Examples of roles for Windows NT and 2000 computers are LM_Workstation, LM_Server, SQLServer, Primary_Domain_Controller, Print, Master_Browser, and Backup_Browser.

WMI array properties can contain one or more items. If empty, they contain a Null value. The Lbound and Ubound functions are used to determine the upper and lower index of the array, because it's not guaranteed the provider will return an array starting with 0 or 1 subscript:

'get a reference to local computer Odin
Set objWMIObject = _
 GetObject("winmgmts:{impersonationLevel=impersonate}" & _
 "!Win32_ComputerSystem='Odin'")

'check if empty array and then print each role
If Not IsNull(objWMIObject.roles) Then
 For nF = Lbound(objWMIObject.roles) To Ubound(objWMIObject.roles)
 WScript.Echo objWMIObject.roles(nF)
 Next
End If

See Also

See the following topics from the WMI SDK: "Object Creation and Monikers" and "Connecting To WMI." For more information, read the MSDN Library article "Win32_ComputerSystem" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32os2_5ijx.asp).

Obtaining IP Information

Problem

You want to determine IP information for the active network cards that are installed on your computer.

Solution

Use the ExecQuery method of the WMI service object to execute a WQL query against the Win32_NetworkAdapterConfiguration class, specifying criteria so only IP-enabled network adapters are returned.

The following sample script lists the physical MAC address and IP address(es) for each IP-enabled device:

'IPMacInfo.vbs
'list IP and MAC information for local computer
Dim objServices, objWMIObjects, objWMIObject, nF

'create Services object for default namespace on local computer
Set objServices = GetObject("winmgmts:{impersonationLevel=impersonate}")
'get all instances of IP enabled devices for
'Win32_NetworkAdapterConfiguration class
Set objWMIObjects = _
 objServices.ExecQuery(_
 "Select * From Win32_NetworkAdapterConfiguration" _
 & "Where IPEnabled = True")

'enumerate each Win32_NetworkAdapterConfiguration instance
For Each objWMIObject In objWMIObjects
 WScript.Echo objWMIObject.Caption & "has the MAC address "_
 & objWMIObject.MACAddress
 'make sure array is not empty
 If Not IsNull(objWMIObject.IPAddress) Then
 'list all associated IP addresses with adapter
 For nF = 0 To UBound(objWMIObject.IPAddress)
 WScript.Echo " "& objWMIObject.IPAddress(nF)
 Next
 End If
Next

Discussion

The Win32_NetworkAdapterConfiguration class contains information related to network adapters installed on your computer. A network adapter refers to any device that is bound to an address, and it may be a physical device, such as a network card, or a virtual device, such as an RAS service or proxy agent.

You may have other network devices that are not IP-enabled. An instance of the Win32_NetworkAdapterConfiguration class has an IPEnabled Boolean property that if set to True is bound to an IP address.

You could enumerate all instances of the Win32_NetworkAdapterConfiguration class to filter out any IP-enabled instances, or alternatively you could execute a query against the WMI service provider to return only the instances that meet the criteria.

WMI allows for SQL-like queries to be executed against the WMI Service provider. These queries return information limited by the criteria in the query:

Set objWMIObjectSet = objService.ExecQuery(strQuery)

The strQuery parameter represents the query to be executed. The query is defined using WQL, which resembles SQL. The query starts with a SELECT statement followed by properties to return and criteria:

SELECT fieldcriteria FROM WMIClass WHERE Criteria

WQL queries cannot contain ORDER BY statements like SQL dialects, nor can it contain any functions.

A successfully executed query returns the results in the form of a collection of instances of the object. This is the same type of collection returned by the InstancesOf method except it only returns instances that meet any criteria in the query.

Table 10-3 lists commonly referenced network device properties.

Table 10-3: Win32_NetworkAdapterConfiguration Properties

PROPERTY

TYPE

DESCRIPTION

IPAddress

Array of strings

IP addresses associated with the device.

DefaultIPGateway

Array of strings

Computer gateways associated with the computer. The default gateway is the first element of the array.

DHCPEnabled

Boolean

If True, DHCP is enabled; otherwise, False.

MACAddress

String

Physical MAC address.

WINSPrimaryServer

String

Address of primary WINS server.

WINSSecondaryServer

String

Address of secondary WINS server.

DNSEnabledForWinsResolution

Boolean

If True, DNS for Windows name resolution is enabled.

DNSDomain

String

Name of DNS domain.

DNSHostName

String

Name of DNS host.

This information can be queried using the following command-line script, ipinfo.wsf:




 

The ipinfo.wsf script displays information for any IP-enabled network device it finds. It functions similarly to the Windows NT ipconfig utility, listing the device description, IP address, MAC address, and DHCP and WINS settings for each device.

The script must be run from the DOS command. It requires no parameters, but it can take an optional computer name as a parameter. If a computer name is specified, the script attempts to connect to the computer using WMI and list the IP information for that computer.

The ipinfo.wsf script uses functions from the wmiinc.vbs support code file. The wmiinc.vbs file contains a number of WMI-related routines for performing date conversion, error handling, and connection to WMI services, and it is used in other scripts in this chapter.

'wmiinc.vbs
'contains reusable WMI support code
Option Explicit
Const WMIConst = "winmgmts:{impersonationLevel=impersonate}!"
Const wbemCimtypeDatetime =101
Const wbemCimtypeString = 8
Const wbemCimtypeChar16 = 103
Const Impersonate = 3
'ExitScript
'Displays message and terminates script
'Parameters:
'strMessage Message to display
'bStdOut Boolean value. If true then writes to StdErr
Sub ExitScript(strMessage, bStdOut)

If bStdOut Then
 'get a reference to the StdErr object stream
 WScript.StdErr.WriteLine strMessage
Else
 WScript.Echo strMessage
End If
 WScript.Quit
End Sub

Function Convert2DMTFDate(dDate, nTimeZone)
Dim sTemp, sTimeZone

sTimeZone = nTimeZone
If nTimeZone>=0 Then sTimeZone = "+" & sTimeZone
sTemp = Year(Now) & Pad(Month(dDate), 2, "0") & Pad(Day(dDate), 2, "0")
sTemp = sTemp & Pad(Hour(dDate), 2, "0") & Pad(Minute(dDate), 2, "0")
sTemp = sTemp & "00.000000" & sTimeZone
Convert2DMTFDate = sTemp
End Function

Function Pad(sPadString, nWidth, sPadChar)
 If Len(sPadString) < nWidth Then
 Pad = String(nWidth - Len(sPadString), sPadChar) & sPadString
 Else
 Pad = sPadString
 End If

End Function

'DMTFDate2String
'Converts WMI DMTF dates to a readable string
'Parameters:
'strDate Date in DMTF format
'Returns
'formatted date string
Function DMTFDate2String(strDate)
 strDate = Cstr(strDate)
 DMTFDate2String = Mid(strDate, 5, 2) & "/" & Mid(strDate, 7, 2) _
 & "/" & Mid(strDate, 1, 4) & " " & Mid(strDate, 9, 2) _
 & ":" & Mid(strDate, 11, 2) & ":" & Mid(strDate, 13, 2)
End Function

'check if script is being run interactively
'Returns:True if run from command line, otherwise false
Function IsCscript()
 If StrComp(Right(WScript.Fullname,11)," cscript.exe", vbTextCompare)=0 Then
 IsCscript = True
 Else
 IsCscript = False
 End If
End Function

'GetBinarySID
'Returns user's SID as array of integer values
'Parameters:
'strAccount User account in Domainusername or username format
'Returns
'array of integer values if successful, otherwise Null
Function GetBinarySID(strAccount)
Dim objAccounts, objAccount, bDomain, bFound, objSIDAccount

bDomain = False
bFound = False
'check if a backslash exists in the account name. if so search for
'domainnameaccountname
If InStr(strAccount, "") > 0 Then bDomain = False

'get an instance of the Win32_Account object
Set objAccounts = GetObject(WMICONST & "rootcimv2") _
 .InstancesOf("Win32_Account")

'loop through each account
For Each objAccount In objAccounts
 'if domain name specified, search against account caption
 If bDomain Then
 'check if name is found
 If StrComp(objAccount.Caption, strAccount, vbTextCompare) = 0 Then
 bFound = True
 Exit For
 End If
 Else 'check against just user name
 If StrComp(objAccount.Name, strAccount, vbTextCompare) = 0 Then
 'check if name is found
 bFound = True
 Exit For
 End If
 End If
 Next

'if found then retrieve SID binary array
If bFound Then
Set objSIDAccount=GetObject(WMICONST & "Win32_SID.S"" & objAccount.sid & """)
 GetBinarySID = objSIDAccount.BinaryRepresentation
Else
 GetBinarySID = Null
End If
End Function

Class WMISupport
 Dim objLocator, strErrorMsg, objService
 Dim strServer, strNameSpace, strUserName, strPassword

 'creates WMI session and returns WMI service object
 Function Connect()
 On Error Resume Next
 'set the default return value
 Connect = Null
 'create locator object
 Set objLocator = CreateObject("WbemScripting.SWbemLocator")

 If Err Then
 strErrorMsg = "Error getting reference to WBEM locator object"
 Exit Function
 End If
 'connect to specified machine
 Set objService = objLocator.ConnectServer(strServer, _
 strNameSpace, strUserName, _
 strPassword)

 If Err Then
 strErrorMsg = "Error connecting to "& strServer
 Exit Function
 End If
 'set impersonation level to Impersonate
 objService.Security_.ImpersonationLevel = Impersonate

 If Err Then
 strErrorMsg = "Error setting security level"
 Exit Function
 End If
 Set Connect = objService
 End Function

 Public Property Let Computer (strComputerName)
 strServer = strComputerName
 End Property

 Public Property Let UserName (strUser)
 strUserName =strUser
 End Property

 Public Property Let Password (strPass)
 strPassword = strPass
 End Property

 Public Property Let NameSpace (strNameSpc)
 strNameSpace = strNameSpc
 End Property

 Public Property Get ErrorMessage()
 Set ErrorMessage = strErrorMsg
 End Property
End Class

See Also

See the following topics from the WMI SDK: "WMI Query Language" and "SWbemServices." For more information, read the MSDN Library article "Win32_NetworkAdapterConfiguration" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32hard4_6oq6.asp).

Changing the Location of an NT Dump File

Problem

You want to change the location of the memory dump file for Windows NT.

Solution

You can create an instance of the Win32_OSRecoveryConfiguration class and set the DebugFilePath property:

'osrecover.vbs
Dim objServices
Dim objWMIObject, objWMIObjects
'create an instance of a Services object for the local machine
Set objServices = _
 GetObject("winmgmts:{impersonationLevel=impersonate}!rootcimv2")

'create an instance of the Win32_OSRecoveryOption class
Set objWMIObjects = objServices.InstancesOf _
 ("Win32_OSRecoveryConfiguration")

'loop through each object (there will be only one)
For Each objWMIObject In objWMIObjects
 'set the DebugFilePath property
 objWMIObject.DebugFilePath = "d:MEMORY.DMP"
 'update the settings
 Call objWMIObject.Put_
Next

Discussion

Windows NT/2000/XP recovery information is exposed through the Win32_OSRecoveryConfiguration class. Properties that are available through this class include location of the dump file, notification, and reboot information should Windows NT/2000 encounter a crash (i.e., Blue Screen Of Death, or BSOD).

Table 10-4 lists some the properties that can be modified.

Table 10-4: Win32_OSRecoveryConfiguration Properties

PROPERTY

TYPE

DESCRIPTION

AutoReboot

Boolean

Automatically reboot at BSOD

DebugFilePath

String

File to write debug information in event of BSOD

SendAdminAlert

Boolean

Determines if alert is sent to administrators in event of BSOD

WriteToSystemLogFile

Boolean

Determines if message should be written to Event Viewer system log in event of BSOD

WriteDebugInfo

Boolean

Determines if debug information should be written to file specified by DebugFilePath property

To change a property, update it with the new value you want to assign to it and invoke the object's Put_ method. Object properties are not updated until this method is invoked.

If the properties are successfully updated, the Put_ method returns a WMI Path object. This object contains information about the path to the updated object. If the Put_ method is unsuccessful, it returns an Empty object and generates an error.

To determine if a property can be written to, use the WMI CIM Studio included with the WMI SDK or the WMI SDK documentation at http://msdn.microsoft.com/library.

WMI CIM Studio provides a visual method of inspecting class properties and determining how the can be manipulated. Figure 10-4 shows the Win32_OSRecoveryOption class viewed by the WMI CIM Studio.

click to expand
Figure 10-4: Win32_OSRecoveryOption class details

Table 10-5 describes the class property icons.

Table 10-5: Class Property Icons

ICON

DESCRIPTION

Property can be written to.

System property.

Property inherited from another class.

Local property.

Key property. This is the property used to create instances of the class.

If you do not have the SDK, as a last resort you can read the Managed Object Format (MOF) files. A MOF file contains the definition for WMI classes and is used to define the interface between the provider and WMI.

MOF files are stored under the System32 directory for Windows NT/2000/XP computers or the System directory for Windows 9x/ME. Viewing MOF files is a simple but effective way of determining what properties and methods are exposed in a class. The following definition is for the Win32_OSRecoveryConfiguration and comes from the CIMWIN32.MOF file, which contains the majority of the definitions for the rootcimv2 namespace:

[Dynamic, Provider ("CIMWin32") ,
 Locale(0x409), UUID("{8502C4E8-5FBB-11D2-AAC1-006008C78BC7}") ]
class Win32_OSRecoveryConfiguration:CIM_Setting
{
 [read, write]
 boolean AutoReboot ;
 [read, write]
 string DebugFilePath ;
 [read, key]
 string Name ;
 [read, write]
 boolean OverwriteExistingDebugFile ;
 [read, write]
 boolean SendAdminAlert ;
 [read, write]
 boolean WriteDebugInfo ;
 [read, write]
 boolean WriteToSystemLog ;
};

  Note 

The MOF file structure has been changed in the latest versions of WMI, but it can still be used to determine class information.

See Also

For more information, read the MSDN Library article "Win32_OSRecoveryConfiguration" (http://msdn.microsoft.com/library/en-us/wmisdk/hh/wmisdk/r_32os_48xa.asp).

Setting TCP IP Information

Problem

You want to set network adapter TCP/IP settings.

Solution

You can create an instance of the Win32_NetworkAdapterConfiguration class for a network adapter. The following code sample gets the first network adapter and sets a static IP address:

Const WMICConst = "winmgmts:{impersonationLevel=impersonate}!"
Dim objWMINetConfig, nResult

'get the instance for the first adapter
Set objWMINetConfig = _
 GetObject(WMICConst & "Win32_NetworkAdapterConfiguration.Index=1")

'assign two static IP addresses to the adapter
nResult=objWMINetConfig.EnableStatic(Array("192.168.1.2","192.168.1.3"), _
 Array("255.255.255.0", "255.255.255.0"))

Discussion

Network configuration information is exposed through properties of the Win32_NetworkAdapterConfiguration class. All of the properties are read-only.

A number of methods are exposed through the class that provides the ability to configure network adapters. This includes the ability to set IP addresses, and configure WINS and DHCP.

To set a setting for a specific adapter, get a reference to the adapter you want to access. Each adapter is identified by a number, starting sequentially from either 0 or 1. There is no specific logic as to the order of the adapters, but generally the default network adapter appears as the first device.

Once you have a Win32_NetworkAdapterConfiguration instance, you can invoke a method to modify an IP-related setting. The following sample renews the DHCP address associated with the network adapter with ID 1:

Const WMIConst = "winmgmts:{impersonationLevel=impersonate}!"
Dim objWMINetConfig
'get the instance for the adapter with ID 1
Set objWMINetConfig = _
 GetObject(WMIConst & "Win32_NetworkAdapterConfiguration.Index=1")

'renew the DHCP address for the adapter
objWMINetConfig.RenewDHCPLease

A number of DHCP-related operations can be executed by calling any of the methods listed in Table 10-6 from an instance of the Win32_NetworkAdapterConfiguration class.

Table 10-6: Win32_NetworkAdapterConfiguration Class Methods

METHOD

DESCRIPTION

EnableDHCP

Enables DHCP addresses for the adapter. Any static IP addresses associated with the adapter are lost.

RenewDHCPLease

Renews the DHCP lease for the adapter.

ReleaseDHCPLease

Releases the DHCP lease for the adapter.

These methods return 0 if they are successful. If a nonzero value is returned, an error occurred while performing the operation. Runtime errors generally do not occur if the execution of the method fails.

To set a static IP address for an adapter, use the EnableStatic method. The syntax is as follows:

nResult = objWMIObject.EnableStatic(aIpAddress,aSubnetMask)

aIpAddress is an array of IP addresses and aSubnetMask is an array of corresponding subnet mask addresses. The earlier Solution script assigns two IP addresses to an adapter. Setting a static IP address overrides the existing DHCP settings, while enabling DHCP disables any static IP addresses.

Network gateways and WINS servers can also be set. The SetWINSServer method sets an IP address for the primary and optionally the secondary server:

nResult = objWMINetConfig.SetWINSServer(strPrimaryServer[, strSecondaryServer])

strPrimaryServer is the IP address for the primary WINS server. The optional strSecondaryServer argument sets the secondary WINS server.

nResult = objWMINetConfig. SetGateways (aGateWays)

The SetGateways method takes an array of strings as a parameter. Each element of the array can contain an IP address representing a WINS gateway.

These methods return 0 if they are successful. If a nonzero value is returned, an error occurred during the execution of the method.

Const WMICONST = "winmgmts:{impersonationLevel=impersonate}!"
Dim objWMINetConfig, nResult

'get the instance for the first adapter
Set objWMINetConfig = _
 GetObject(WMICONST & "Win32_NetworkAdapterConfiguration.Index=1")

'set the primary WINS server
nResult = objWMINetConfig.SetWINSServer("192.161.1.1")
'set WINS gateway
nResult = objWMINetConfig.SetGateways(Array("192.161.1.1"))

The SetWINSServer method in the previous sample only set the first parameter, PrimaryWINSServer. While this is valid, any value in the secondary WINS server will be overwritten, even though the parameter wasn't specified.

When you set multiple gateway addresses, the first array element represents the default gateway.

  Note 

The OS you are executing these methods under may impose limitations on the functionality of the method. For example,Windows 9x does not support multiple IP addresses per adapter.

There are network settings that apply to all IP-enabled adapters as a whole and are not set per adapter. Methods that can only be invoked on class objects and not instances of a class are known as static methods.

For example, the RenewDHCPLeaseAll and ReleaseDHCPLeaseAll methods affect the DHCP settings for all adapters.

To determine if a method is static, use the WMI CIM Studio to view the qualifiers for the method. To view method qualifiers, find the method for the appropriate class you are querying and double-click the class. Figure 10-5 shows the qualifiers for the EnableWINS method.

click to expand
Figure 10-5: EnableWINS qualifiers

The Static qualifier indicates the method can only be invoked on the class object.

The following sample renews the DHCP leases for all adapters:

Const WMICONST = "winmgmts:{impersonationLevel=impersonate}!"

Dim objWMINetConfig, nResult

'get an instance of the Win32_NetworkAdapterConfiguration class
Set objWMINetConfig = _
 GetObject(WMICONST & "Win32_NetworkAdapterConfiguration")

'set the primary WINS server
nResult = objWMINetConfig.RenewDHCPLeaseAll

Table 10-7 lists static methods.

Table 10-7: Win32_NetworkAdapterConfiguration Static Methods

METHOD

DESCRIPTION

RenewDHCPLeaseAll

Renews all DHCP addresses for all adapters

ReleaseDHCPLeaseAll

Releases the DHCP lease for the adapter

The following script, ipmaint.wsf, provides general-purpose IP maintenance facilities. It allows network settings for static IP, DHCP, WINS, and DNS settings to be manipulated.




 

To get the command-line syntax, run the ipmaint.wsf script from a command line with no parameters.

See Also

For more information, read the MSDN Library article "Win32_NetworkAdapterConfiguration" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32hard4_6oq6.asp).

Inventorying Computer Components

Problem

You want to inventory the main components of a computer.

Solution

You can use the following command-line script to inventory computer components such as BIOS, CPU, memory, OS, hard drive, video, network adapter, modem, and SCSI controllers. The script uses the ENTWSH.SysInfo component from Solution 10.1 to get some of the information.




 

Discussion

WMI services expose a number of classes that can be used to query computer configuration. Table 10-8 lists a number of WMI classes that expose commonly queried system properties.

Table 10-8: WMI Computer Information Classes

CLASS

DESCRIPTION

Win32_NetworkAdapter

Network adapter information, such as IP information, model information, and the physical MAC address.

Win32_DiskDrive

Disk drive information. Includes model, capacity, adapter, manufacturer, and size.

Win32_VideoConfiguration

Video adapter configuration, such as adapter type and current resolution settings.

Win32_SCSIController

SCSI controller information.

Win32_POTSModem

Modem information and configuration.

Use the WMI CIM Studio (see Solution 10.2) included with the SDK to browse the available classes and their associated properties exposed through WMI.

All properties might not be available for all classes listed. Some properties may be available on some OSs but not others, even if they are running on the same machine. This is generally related to features supported under a given OS, so Windows 2000 might return more properties for a given device than Windows NT 4.0 as a result of plug-and-play support.

The inventory.wsf script inventories the local computer's main components.

See Also

For more information, read the MSDN Library article "Computer System Hardware Classes" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32hard1_9v77.asp).

Executing Generic WMI Queries

Problem

You want a command-line script to execute WMI queries and then pipe the output to standard output.

Solution

The following command-line script executes a WQL query and sends output to standard output:




 

Discussion

The command-line wmiexec script executes a WQL query and outputs the results the standard output.

The following command line outputs disk drive information for the local machine:

wmiexec "Select Description, InterfaceType, Model, Size From Win32_DiskDrive" /H

Output is delimited by commas. Any string values are surrounded by double quotes. Field names are not output unless specified by using the /H switch.

You may want to execute a query that requires calculated criteria, such as the current date or time. WQL queries passed to the wmiexec script can contain VBScript functions to perform calculations. Any statement surrounded by and /> will be evaluated.

The ability to pass evaluate statements in the command line allows generic queries to be executed where the appropriate criteria is filled in. In the following example, all properties are queried for the Win32_ComputerSystem class where the computer name matches the local computer name:

wmiexec.wsf "Select * From Win32_ComputerSystem Where Name=''"

The ComputerName function is evaluated between and /> and returns the local computer name.

The following example returns all items from the Applications event log within the last 48 hours:

wmiexec.wsf "Select Category, ComputerName, EventIdentifier, Message, SourceName
, TimeGenerated FROM Win32_NTLogEvent WHERE LogFile='Application' AND
TimeWritten > ''"

The result of the statement executed between and /> is inserted into the query. It uses the Convert2DMTFDate function included in the wmiinc.vbs support code file to return the time from 2 hours ago to DMTF format (see Solution 10.14 for details on Event Viewer access).

Double quotes cannot be used in a command-line parameter, so use the grave accent (`) character (ASCII value 96) instead. This character is usually located above the Tab key on a keyboard. It is replaced in the command-line string with double quotes before the query is executed.

Queries can be executed against WMI providers on a remote computer by providing the /C switch together with the name of the remote computer. The following command line lists all running processes on the remote computer Odin:

wmiexec "Select Caption, ExecutablePath From Win32_Process" /h /c odin

Table 10-9 lists available optional switches.

Table 10-9: WMIExec Command-Line Switches

SWITCH

DESCRIPTION

/H

Shows headers for each field name.

/U

User name to connect with.

/P

Password for specified user.

/N

WMI namespace. Default is rootCIMV2.

/C

Name of remote computer to query. Default is local.

/D:

Delimiter for output. Default is comma.

/Q:

Quote character for string values. Default is double quotes.

Changing Environment Variables

Problem

You want to change environment variables for all users on a computer.

Solution

You can enumerate all instances of the Win32_Environment class and then modify any instances in which the environment variable name is TMP or TEMP:

'envtmpchng.vbs
'changes the location of temporary file environment
'variables Tmp and Temp
Dim objServices
Dim objWMIObject, objWMIObjects

'get a reference to a WMI service
Set objServices = _
 GetObject("winmgmts:{impersonationLevel=impersonate}")
Set objWMIObjects = objServices.InstancesOf("Win32_Environment")
On Error Resume Next
'loop through each environment variable for temp
For Each objWMIObject In objWMIObjects
'check if environment variable is TEMP or TMP
If objWMIObject.Name = "TEMP" Or objWMIObject.Name = "TMP" Then
 objWMIObject.VariableValue = "d:	emp"

 'update the settings
 Call objWMIObject.Put_
 End If
Next

Discussion

Under Windows NT, environment variables can be modified for the current logged-on user. A profile is created for each user that uses the NT machine. The profile stores a copy of the user's local environment variables.

The Shell object's Environment object can change a variable for the current user, but not for any other profiles stored on the local system. The WMI object exposes environment variables through the Win32_Environment class.

If the user is logged on with administrative rights, he or she can access the environment variables of all profiles on the local machine.

The Win32_Environment class key is a combination of the environment variable name and user name. The user name and environment variable name are exposed through the Win32_Environment class as the UserName and Name properties, respectively. The user name can optionally have a domain name and backslash prefixed to it to distinguish it from a local or domain account.

To reference an instance of a WMI object with a multivalue key, specify the criteria for each field separated by a comma.

The following example gets an instance of the environment variable Temp for user Fred and sets the value to d: emp:

Dim objServices, objWMIObject
'get a reference to a WMI service
Set objServices = _
 GetObject("winmgmts:{impersonationLevel=impersonate}")

'gets a reference to the environment variable TEMP for user Administrator
Set objWMIObject = objServices.Get _
 ("Win32_Environment.Name='TEMP',UserName='C3IAdministrator'")

objWMIObject.VariableValue = "d:	emp"
Call objWMIObject.Put_

Windows 9x/ME machines can list environment variables but cannot modify the values.

See Also

Solution 2.3. For more information, read the MSDN Library article "Win32_Environment" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32os3_4dbo.asp).

Terminating a System Process

Problem

You want to terminate a system process.

Solution

You can get a reference to the system process you want to terminate by querying Win32_Process for the handle (process ID) for the process you want to terminate. You can invoke the Terminate method on the process object in this way:

Dim objServices, objWMIObject, nResult
 Set objServices = GetObject("winmgmts:{impersonationLevel=impersonate}")
Set objWMIObject = objServices.Get("Win32_Process.Handle=326")
nResult = objProcess.Terminate(0)

Discussion

System processes are exposed through the WMI Win32_Process class. Access to process information is available to Windows NT/2000/XP/9x/ME.

Each process is identified by a handle/process ID (PID). The PID is a numeric identifier assigned to the process when the process is created. The process handle is unique for each instance of the process. The following script lists all running processes with their handle and executable name:

Dim objWMIObjects, objWMIObject, objServices
Set objServices = _
 GetObject("winmgmts:{impersonationLevel=impersonate}!rootcimv2")
'create an instance of the Win32_Process class
Set objWMIObjects = objServices.InstancesOf("Win32_Process")

'loop through each process and list the handle and executable
For Each objWMIObject In objWMIObjects
 WScript.Echo objWMIObject.Handle & ""& objWMIObject.ExecutablePath
Next

The PID is exposed through the Handle property. The path to executable represented by the process can be retrieved through the ExecutablePath property, while the Description, Name, and Caption properties return the executable name.

To terminate an existing process, get a reference to the process you want to terminate and invoke the Terminate method. The syntax is as follows:

nResult = objProcess.Terminate(nReason)

The nReason parameter is a process-specific reason code. Unless you know of any specific values to pass to a process, this value is 0. The Terminate method returns 0 if successful—any other value indicates that an error occurred.

The following script, procmaint.wsf, allows for processes to be listed and terminated for local or remote computers:




 

Execute the procmaint.wsf script from the command line without any parameters to retrieve the syntax.

See Also

For more information, read the MSDN Library article "Managing Windows with WMI" (http://msdn.microsoft.com/library/techart/mngwmi.htm).

Starting an Application on a Remote Computer

Problem

You want to start an application on a remote computer.

Solution

You can create an instance of the Win32_Process class, specifying the remote computer on which you want to start the application. Use the Win32_Process object's Create method to start the application on the remote machine.

'get a reference to the Win32Process class object on specified machine
Set objProcess=GetObject("winmgmts:{impersonationLevel=impersonate}!" & _
 "\Odin
ootcimv2:Win32_Process")
 'create process on remote machine
nResult = objProcess.Create("notepad.exe", , ,nProcID)
WScript.Echo "The PID for the new instance of notepad is "& nProcID

Discussion

Applications can be started locally using the Shell object's Run method, but this method cannot start remote instances of an application. Applications can be executed on a remote machine using the Create method of the Win32_Process class. The syntax is as follows:

nResult = objProcess.Create(strApp,strCurrentDir,objProcessStartInfo,nProcID)

strApp represents the name of the application to start. If no explicit path to the application is specified, the directories specified in the PATH environment variable are searched.

strCurrentDir is an optional parameter that identifies the path to the start-up directory for the application.

The optional objProcessStartInfo parameter is an instance of the Win32_ProcessStartup class that contains start-up information, such as application title, environment variables, and application appearance.

The nProcID parameter is the numeric process ID assigned to the new process. This is set by the Create method-you cannot assign your own process IDs.

The Create method returns 0 if the process was successfully created. A nonzero value is returned if an error occurred while attempting to start the remote application, and a runtime error is not generated if the remote application is not successfully started. You must have appropriate administrative rights to create processes on remote machines.

The following rmtexecute.wsf command-line script allows for the execution of applications on remote computers:




 

Execute the script from the command line, passing the computer name and the name of the application to execute:

rmtexecute.wsf thor notepad.exe

If you do not specify the full path, the directories specified in PATH environment variable search for the application.

See Also

For more information, read the MSDN Library articles "Win32_Process" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32os5_02er.asp) and "Create Method in Class Win32_Process" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32os5_3q5v.asp).

Compressing Folders and Files

Problem

You need to compress all folders over a certain size.

Solution

The following script applies the compressed attribute to all user folders that are over 25MB:

'compress.vbs
Option Explicit
Dim objFSO, strWMIPath, objService, objFolders, objFolder, objWMIObject
Set objFSO = CreateObject("Scripting.FileSystemObject")
'get a reference to a WMI service on the local machine
Set objService = _
 GetObject("winmgmts:{impersonationLevel=impersonate}!rootcimv2")

'get the folder to search
Set objFolders = objFSO.GetFolder("D:Users")

For Each objFolder In objFolders.SubFolders
 'if folder over certain size, then compress
 If objFolder.Size > 25000000 Then
 'get a reference to the directory to compress
 Set objWMIObject = _
 objService.Get("Win32_Directory.Name=" & chr(34) & _
 Replace(objFolder.Path,"","\") & chr(34))
 objWMIObject.Compress
 WScript.Echo "Compressed folder "& objFolder.Path
 End If
Next

Discussion

Windows NT and Windows 2000/XP enable you to compress files and folders.

The Compress method is exposed through the CIM_LogicalFile class. Instances of files and directories are exposed through the Win32_Directory and CIM_DataFile classes respectively, which inherit the Compress method from the CIM_LogicalFile class.

The following sample compresses a local directory and file:

Dim objService, objWMIObject, nResult
'get a reference to a WMI service
Set objService = GetObject("winmgmts:{impersonationLevel=impersonate}")

'get a reference to the directory D:DataReports and compress it
Set objWMIObject = _
 objService.Get("Win32_Directory.Name="" D:\Data\Reports""")
nResult = objWMIObject.Compress

'get a reference to the file D:Datadata.mdb and compress it
Set objWMIObject = _
 objService.Get("CIM_DataFile.Name="" D:\Data\data.mdb""")
nResult = objWMIObject.Compress

Paths to directories and files cannot be in UNC format. Backslashes in the path must be prefixed with another backslash. The Compress method returns 0 if successful.

The WMI provider allows for decompression in version 1.5 and later. Windows 2000/XP includes version 1.5 as standard, but if you are running Windows NT 4.0 you might have an older version of WMI. The version 1.5 provider exposes an Uncompress method that can decompress files or folders:

Dim objService, objWMIObject, nResult
'get a reference to a WMI service
Set objService = GetObject("winmgmts:{impersonationLevel=impersonate}")
'get a reference to a directory
Set objWMIObject = _
 objService.Get("Win32_Directory.Name="" D:\Data\Reports""")
'decompress directory
nResult = objWMIObject.Uncompress

The Uncompress method returns 0 if successful.

Queries can be executed against the CIM_DataFile class to return files that meet certain criteria. The following sample uncompresses all ZIP files on the D: drive on the local machine. Because ZIP files are already compressed, unnecessary CPU time is used when accessing them.

Dim objService, objWMIFiles, nResult, objFile

On Error Resume Next

'get a reference to a WMI service
Set objService = GetObject("winmgmts:{impersonationLevel=impersonate}")

'return all zip files from the D: drive that are compressed
Set objWMIFiles = _
 objService.ExecQuery("Select * From CIM_DataFILE Where Drive='D:'" & _
 " And Extension='zip' And Compressed=True")
'loop through any compressed files and uncompress them
For Each objFile In objWMIFiles
 WScript.Echo "Uncompressing file "& objFile.Name
 objFile.Uncompress
Next

See Also

For more information, read the MSDN articles "Win32_Directory" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32os2_448p.asp) and "Win32_NTEventlogFile" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32os4_4ag5.asp).

Copying Files on a Remote Computer

Problem

You want to copy a file on a remote computer.

Solution

File manipulation can be easily performed using the File System Object (FSO). But FSO methods assume that a path exists to the files you are manipulating, by either a physical or UNC path.

The WMI CIM_DataFile class allows for files to be manipulated on remote machines that have not shared directories.

The following code gets a reference to the file report.doc on the remote computer Odin and copies it to a backup directory:

Dim objServices, nResult, objFile
'connect to remote computer Odin
Set objServices = GetObject("winmgmts:{impersonationLevel=impersonate}!\Odin")
'get a reference to file reports.doc
Set objFile = _
 objServices.Get("CIM_DataFile.Name='d:\data\reports.doc'")
'copy file to backup reports directory
nResult = objFile.Copy("d:\backup\reports
eports.doc")

Discussion

WMI provides methods for copying, deleting, and renaming files. These operations can be performed more easily using the File System Object (FSO), but WMI has some advantages when performing operations on remote machines.

  • A network path to the file or directory does not need to exist. The FSO requires a connection to a network share. File operations can be performed on computers that have no shared resources.
  • Network traffic. Copying and moving local files on a remote computer are executed by the remote WMI provider, and no traffic is sent back to the calling machine. Any copy or move operation performed by FSO methods, Explorer, or existing command-line utilities like copy transfer data between the calling and remote computer. This is useful over slow links when working with large files.

Files are referenced through the CIM_DataFile class. When referencing a file, any path separators (backslashes) must be prefixed by a second backslash.

Once you have a reference to a file, you can copy or rename it. The syntax is as follows:

nResult = objFile.Copy| Rename(strDestination)

The strDestination parameter identifies the path name of the file you are copying or moving the source file to. It must point to a local path on the machine you are copying the file to; a UNC network path cannot be used. You must specify the full path, including the name of the file. Specifying only the desti-nation directory will not automatically copy or move the file to that directory.

The methods return 0 if the operation was successful. If the destination path is invalid, an empty value is returned. If the destination file already exists, it is not overwritten and an error value is returned.

Wildcards cannot be specified using these methods-however, a query can be executed against the provider and the results processed. In the following sample, all temporary files from the C: drive are deleted:

Dim objService, objWMIFiles, nResult, objFile
'get a reference to a WMI service
Set objService = GetObject("winmgmts:{impersonationLevel=impersonate}")

'get all files with .tmp extenstion on the C: drive
Set objWMIFiles = _
objService.ExecQuery ("Select Name From CIM_DataFILE Where "& _
 "Drive='C:' And Extension='tmp'")
'loop through all files and attempt to delete them
For Each objFile In objWMIFiles
 nResult = objFile.Delete
 If nResult <> 0 Then
 WScript.Echo "*Unable to delete "& objFile.Name
 Else
 WScript.Echo "Successfully deleted file:" & objFile.Name
 End If
Next

The Delete method returns 0 if successful. Deleted files are not moved to the Recycle Bin.

Directories can be copied, renamed, and deleted using the same method as the CIM_DataFile class. To perform these operations on a directory, get a reference to the directory through the Win32_Directory class.

Once you have a reference to a directory, you can invoke the Copy, Rename, or Delete method. The following example makes a copy of the directory D:data to D:data backup on the remote computer Odin:

Dim objServices, nResult, objDir

'connect to remote computer Odin
Set objServices = _
 GetObject("winmgmts:{impersonationLevel=impersonate}!\Odin")

'get a reference to directory
Set objDir = objServices.Get("Win32_Directory.Name='d:\data'")

'copy to directory to data backup
nResult = objDir.Copy("d:\backup\data")

These methods return 0 if successful. The Copy method copies an existing directory structure, including all files and subdirectories. If the directory already exists, nothing is copied.

The Delete method deletes the whole directory structure if there are files and subdirectories in the directory you are trying to delete.

Appropriate security access is required to perform any file operations on a remote computer.

The following rmtcopy.wsf script copies individual files on a remote computer using WMI:




 
 

The script requires the name of the remote computer followed by the path to the source and destination files:

rmtcopy.wsf d:data
eport.doc d:ackup
eport.doc

See Also

For more information, read the MSDN Library articles "Win32_Directory" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32os2_448p.asp) and "Win32_NTEventlogFile" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32os4_4ag5.asp).

Rebooting a Computer

Problem

You want to reboot a computer.

Solution

You can get the active "primary" OS for the computer you want to reboot by executing a query against the Win32_OperatingSystem class. Then you call the Reboot method.

The following example reboots the remote computer Thor:

Dim nStatus, objService, objWMIObject, objWMIObjects
'create process on remote machine
Set objService = _
 GetObject("winmgmts:{impersonationLevel=impersonate,(Shutdown)}!\thor")
'get the active OS
Set objWMIObjects = objService.ExecQuery _
 ("Select * From Win32_OperatingSystem Where Primary = True")

For Each objOS In objWMIObjects
 Set objWMIObject = objOS
Next
nStatus = objWMIObject.Reboot

Discussion

A computer can be shut down or rebooted by using the ShutDown or Reboot methods exposed through the Win32_OperatingSystem class. First, get a reference to the computer you want to shut down/reboot-this may be a local or remote machine. If the machine is remote, you must be logged on with appropriate administrative access or supply the appropriate credentials.

You must also specify the Shutdown privilege in the connection string to perform shutdowns or reboots for local computers. A privilege is setting that is required to be specified for certain operations. Even if you have the appropriate level of security access to perform the operation, you must still specify the privilege.

Privileges can be passed with the connection string moniker when you create a Services object:

Set objService = _
 GetObject("winmgmts:{impersonationLevel=impersonate,(Shutdown)}")

All methods invoked using this Services object will inherit the privilege. To determine if a method requires privileges or not, use WMI CIM Studio to inspect the method you need to use-in this case, the Reboot method. Figure 10-6 shows the Reboot method under WMI CIM Studio.

click to expand
Figure 10-6: The Reboot method in WMI CIM Studio

If you see a Privileges qualifier in the list, this indicates that a privilege is needed to call the method on a local machine. Click the button to list the privilege(s) required for the method. This will list the privileges in the format SePRIVILEGEPNAMEPrivilege, where PRIVILEGEPNAME represents the name of the privilege to be used in the connection string. The Reboot method will show the SeShutdownPrivilege qualifier under WIM CIM Studio, and it will use Shutdown in the connection string.

Get a reference to an instance of the active OS for the machine you want to shut down. You can retrieve the reference by querying the Primary property of the Win32_OperatingSystem class. The instance where the Primary property is True is the active OS.

Then invoke the Shutdown or Reboot method. The syntax is as follows:

nStatus = objWMIInstance.ShutDown | Reboot

Both the Reboot and Shutdown methods forcibly terminate any running applications. If you have an application with unsaved data, the information will be lost if these methods are used.

The methods return 0 if the operation completed successfully.

The Win32_OperatingSystem class also exposes a Win32Shutdown method that provides additional functionality over the Reboot and Shutdown methods on Windows NT and Windows 2000 computers. The syntax is as follows:

nStatus = objWMIInstance.Win32ShutDown(nConstant)

The nConstant parameter represents one value or a combination of multiple values listed in Table 10-10.

Table 10-10: Win32ShutDown Argument Values

CONSTANT

VALUE

DESCRIPTION

EWX_LOGOFF

0

Logs machine off

EWX_SHUTDOWN

1

Shuts down machine

EWX_REBOOT

2

Reboots machine

EWX_FORCE

4

Forcibly closes any running applications

EWX_POWEROFF

8

Powers off machine

When you attempt to shut down, log off, or reboot a computer, Win32ShutDown will check if there are unsaved documents open and the applications will prompt accordingly.

For example, if you have an unsaved Office document and you attempt to shut down the computer using Win32ShutDown, you will be prompted to save the document. If the prompt is cancelled, the shutdown procedure is terminated.

Adding the EWX_FORCE constant to any of the other values forcibly terminates any applications that are running in a manner similar to the Reboot and Shutdown methods.

To force a logoff, pass the value of 5, which is a combination of EWX_SHUTDOWN (1) and EWX_FORCE (4).

Windows NT 4.0 does not support being powered off. Attempting to power off an NT 4.0 machine will have the same effect as rebooting the machine.

The following script performs reboots on remote computers:

'reboot.vbs
'reboots local or remote computer
 Dim objOS, nStatus, objService, objWMIObject, objWMIObjects, strMachine
On Error Resume Next
 strMachine = ""
 'check if argument passed, if so assume remote computer
 'to reboot
 If WScript.Arguments.Count = 1 Then
 strMachine = "!\" & WScript.Arguments(0)
 End If

 'create instance of WMI service with Shutdown privilege
 Set objService = GetObject( _
 "winmgmts:{impersonationLevel=impersonate,(Shutdown)}" _
 & strMachine )

 If Err Then
 WScript.Echo "Error getting reference to computer "& strMachine
 End If

 'get the primary O/S to reboot
 Set objWMIObjects = objService.ExecQuery( _
 "Select * From Win32_OperatingSystem Where Primary = True")

 'get the instance of the O/S to reboot For Each objOS In objWMIObjects
 Set objWMIInstance = objOS
 Next

 nStatus = objWMIInstance.Reboot()
 If nStatus = 0 Then
 WScript.Echo "Computer successfully rebooted"
Else
 WScript.Echo "Error rebooting computer: Status returned by Reboot:" & nStatus
End If

The command-line script requires a computer name to be passed. The script attempts to reboot the specified computer.

See Also

Read the following topics in the WMI SDK documentation: "Setting Privileges for the Scripting API," "Calling the Method," and "Security Issues When Writing WMI." For more information, read the MSDN Library article "Win32_OperatingSystem" (http://msdn.microsoft.com/library/psdk/wmisdk/clasops_0h7x.htm).

Checking the Event Viewer for Unauthorized Access

Problem

You want to check the Event Viewer for any file audit events in order to determine unauthorized file access.

Solution

You can execute a query against the Win32_NTLogEvent class to return all records for event identifiers that meet certain criteria. In the case of unauthorized file access (trapped via file auditing), this is event 560:




 

Discussion

Event log information is exposed through the Win32_NTLogEvent class. Using the ExecQuery statement, queries can be executed against the WMI provider to return event log information that meets certain criteria.

Windows NT 4.0 exposes security, application, and system logs. Windows 2000/XP includes these logs as well as service-specific logs, such as DNS and directory services.

If you are uncertain of the names of available logs, use the following code sample to list the available log files. You can use these log file names when you query the Win32_NTLogEvent class:

'list event logs
Dim objWMIObjects, objWMIObject

Set objService = GetObject("winmgmts:{impersonationLevel=impersonate}")
Set objWMIObjects = objService.InstancesOf("Win32_NTEventLogFile")

'loop through and list all available event logs
For Each objWMIObject In objWMIObjects
 WScript.Echo objWMIObject.LogFileName
Next

Each log exposes events related to the log type.

Table 10-11 lists the Win32_NTLogEvent object's properties.

Table 10-11: Win32_NTLogEvent Object Properties

PROPERTY

DESCRIPTION

EventIdentifier

Application-specific event identifier.

TimeWritten

Time event was written to the log in DMTF format.

TimeGenerated

Time event was generated in DMTF format. Same as TimeWritten.

Type

Event type. Can be error, information, warning, audit failure, or audit success.

User

User name. If not available, returns Null value.

SourceName

Source application or service that generated the event.

Category

Numeric value representing category. Represents the descriptive category displayed in Event Viewer and is application specific. There is no method of mapping the numeric value returned by this property to the descriptive category that appears in Event Viewer via WMI.

Message

The event message.

Data

Array of byte values representing any additional data stored in event.

InsertionStrings

Array of strings inserted into event message.

The TimeWritten property is in DMTF date format, which is returned as a string in the following format:

yyyymmddHHMMSS.mmmmmmsUUU

where yyyy is a four-digit year, mm is two-digit month (01-12), dd is a two-digit day, HH is the hour in 24-hour clock format, MM is minutes, SS is seconds, and mmmmmm is microseconds.

The last four characters (sUUU) represent the time zone stored in Universal Time Coordinates(UTC), also known as Greenwich Mean Time (GMT). UTC is represented by the number of minutes from GMT. So for the West Coast of the United States, which is 8 hours behind GMT, the UTC time code is -480.

This number doesn't take into consideration issues such as daylight saving time. To get the current time zone settings, get a reference to the CurrentTimeZone property for the Win32_ComputerSystem class.

The following code snippet gets the time zone for the local computer Odin:

Dim objWMI, nTimeZone
'get a reference to instance of Win32_ComputerSystem class for computer Odin
Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}" & _
 "!Win32_ComputerSystem='Odin'")

nTimeZone = objWMI.Currenttimezone

The Convert2DMTFDate function from the wmiinc.vbs support file provides the conversion of dates to the DMTF data format. The syntax is as follows:

strResult = Convert2DMTFDate(dDate, nTimeZone)

The dDate parameter is the date and optional time you want to convert and the strTimeZone parameter represents the time zone as a numeric value.

Also included in the wmiinc.vbs file is the DMTFDate2String function, which converts DMTF dates stored in WMI date/time properties to a "readable" date format. The syntax is as follows:

strDate = DMTFDate2String (strDMTFDate)

The strDMTFDate parameter contains the DMTF date to convert.

If you are querying event records from the Security event log, the Security privilege must be assigned to the user. Assigning the Security privilege to a user doesn't affect the querying of other logs, but it is required for the Security log.

Event log records expose an InsertionStrings property. This property is an array of values that are inserted into the event message.

Insertion string order is event specific. In the Solution script, the InsertionStrings are checked if the audit event was for file access.

The following code sample returns all of the Security log events with event ID 529 or 539, which are logon failures. This is useful for identifying locked-out accounts and potential security breaches:




 

The script requires a computer name to be passed as a parameter to the script from the command prompt. This allows multiple sources to be checked.

The following batch file outputs all logon problems to a text file called logprob.txt for the computers Thor, Odin, and Loki:

cscript logonoffchk.wsf thor > logprob.txt
cscript logonoffchk.wsf odin > logprob.txt
cscript logonoffchk.wsf loki > logprob.txt

  Note 

Accessing large event logs, especially on remote computers, can be time-consuming. The WMI provider can also consume a large number of CPU cycles when initially executing a query, so test for any performance issues with other applications in your environment.

The NT event log is a powerful tool, but it can be time-consuming to filter through the logged information, especially across multiple computers. The following script outputs the details for all warning, error, and audit failure events for the last 24 hours for the computer specified by the command-line parameter:




 

Event messages stored in the Message property of the event object store a carriage return and linefeed (ASCII characters 13 and 10) for each new line. When the message is outputted it appears with an additional line between each line of the message, so strip out the line feed character using the Replace function, as in the previous example.

See Also

Read the following WMI SDK documentation topics: "Setting Privileges for the Scripting API," "Object Creation and Monikers," "Calling the Method," "Security Issues When Writing WMI," and "Date and Time Format." For more information, read the MSDN Library articles "Win32_NTEventLogFile" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32os4_4ag5.asp) and "Managing Windows with WMI" (http://msdn.microsoft.com/library/techart/mngwmi.htm).

Backing Up Event Viewer Events

Problem

You want to back up event logs exceeding a certain record count.

Solution

You can reference an instance of the Win32_NTEventLogFile class for the event log that you want to back up and then invoke the BackupEventlog method.

The Solution script checks all event logs on the local machine, and if there are more than 10,000 events in the log, the events are backed up. The backed up logs are named log month-date-year hh-mm.evt. For example, an Application log backed up at 9:35 PM on February 4 would be stored as Application 2-4-2000 21-35.evt:

'clrevent.vbs
'backs up and clears local event log if number of records is
'more than 5000 records
Dim objWMISet, objInstance, nResult, strFile, objServices
'get an instance of a WMI Service object
Set objServices = _
 GetObject("winmgmts:{impersonationLevel=impersonate,(Backup,Security)}")

'get the instances of the Win32_NTEventLogFile class
Set objWMISet = objServices.InstancesOf("Win32_NTEventLogFile")
 For Each objInstance In objWMISet
 'check if number of event records is more than 5000, clear log
 If objInstance.NumberOfRecords > 5000 Then
strFile = "d:eventlogsackup" & objInstance.LogFileName _
 & " " & MonthName(Month(Date)) & _
 "-" & Day(Date) & "-" & Year(Date) & _
 " " & Hour(Now) & "-" & _
 Minute(Now) & ".evt"

 'backup and clear log
 nResult = objInstance.BackupEventlog(strFile)
 'check if operation successful
 If nResult<> 0 Then
 WScript.Echo objInstance.LogFileName & "backed up to "& strFile
 Else
 WScript.Echo "Error ocurred backing up event log "_
 & objInstance.LogFileName & "to "& strFile
 End If
 End If
Next

Discussion

When you use the Windows NT Event Viewer, you can set event logs to be cleared at certain events automatically, such as when the event log reaches a certain size or a certain number of records. However, there is no option to automatically back up the events that are being deleted. The script backs up the event log after a specified number of events are accumulated.

NT events are exposed through the Win32_NTEventLogFile class. Creating an instance of this class returns a collection of all event logs. On Windows NT 4.0 machines this can be Application, Security, and System. Windows 2000/XP provides these logs as well as additional logs for specific services, such as DNS Server server and Directory service.

If you are backing up the Security event log, you must set the Security privilege when connecting to the namespace.

The NumberOfRecords property returns the number of event log records that exist in the specific event log, while the LogFileName property returns the name of the log (Application, Security, or System).

The event log can be backed up by the BackupEventLog method. The syntax is as follows:

nResult = objInstance.BackupEventlog(strFile)

The strFile parameter specifies the path to the file to back up the event log. The path can be a local path but not a UNC path. The local path is relative to the machine where the event log resides. The method returns 0 if successful.

If a backup file with the same name already exists, it is not replaced and an error value is returned.

The Win32_NTEventLogFile class exposes a ClearEventlog method that clears the event log. The ClearEvent log method can back up the data before clearing any events. The syntax is as follows:

nResult = objInstance.ClearEventlog([strFile])

The optional strFile parameter specifies the path to the file to back up. It operates in the same way as the BackupEventLog method. The method returns 0 if successful. If the file already exists, it is not overwritten. If the optional backup file name is specified, the method will not clear the events unless the data is successfully backed up.

The following code sample gets a reference to the application event log and backs up and clears the events:

Dim objEvt
'get a reference to the Application event log. The key for the
'Win32_NTEventLogFile class is the Name property, which represents the
'path to the event log.
Set objEvt = _
 GetObject("winmgmts:{impersonationLevel=impersonate,(Backup,Security)}" & _
 "!Win32_NTEventLogFile.Name='C:WINNT40System32configAppEvent.Evt'")
 objEvt.ClearEventlog ("D:DataEvenBackupAppBackup.evt")

See Also

For more information, read the MSDN Library articles "Win32_NTEventLogFile" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32os4_4ag5.asp) and "Managing Windows with WMI" (http://msdn.microsoft.com/library/techart/mngwmi.htm).

Processing Event Viewer Events

Problem

You want to process Event Viewer events when an event is generated.

Solution

You can invoke the ExecNotificationQuery method against the WMI namespace you want to process events:

'connect to Services object for local computer
Set objServices = GetObject("winmgmts:{impersonationLevel=impersonate,(Security)}")

'execute an event notification query to generate events when a new
'event record is created
Set objEvents = objServices.ExecNotificationQuery _
 ("select * from __instancecreationevent "& _
 "where targetinstance isa 'Win32_NTLogEvent'")

'check if error occurred during execution of
if Err <> 0 then
 WScript.Echo Err.Description, Err.Number, Err.Source
End If

'wait forever..
WScript.Echo "Waiting for NT objEvents. . ."
Do
 Set NTEvent = objEvents.nextevent
 'check if error occurred
 If Err <> 0 Then
 WScript.Echo Err.Number, Err.Description, Err.Source
 Exit Do
 Else
 WScript.Echo NTEvent.TargetInstance.Message
 End if
Loop

Discussion

The WMI CIM Manager can consume events from WMI providers by executing a notification query against them. A notification query is different than a normal query in that it returns data from events as they occur.

The ExecNotificationQuery method is used to execute a notification query against a WMI provider. The syntax is as follows:

set objEvents = objService.ExecNotificationQuery(strEventQuery)

strEventQuery contains the query to execute and specifies what conditions an event will fire. The query is constructed using WQL statements.

The source for the queries can be the creation of a new instance of a WMI class or the modification of an existing instance. Use the__instancecreationevent statement to specify the creation of a WMI class or__instancemodificationevent to specify the modification of an existing instance of a class.

The following sample executes an event notification query that generates an event whenever a new instance of the Win32_NTLogEvent class is generated. This occurs whenever a new event log item is generated:

Set objService = GetObject("winmgmts:{impersonationLevel=impersonate,(Security)")

Set objEvents = objService.ExecNotificationQuery _
("select * from __instancecreationevent where targetinstance isa "& _
 "'Win32_NTLogEvent'")

If the query executed through the ExecNotificationQuery method is successful, it returns an EventSource object. The EventSource object exposes a NextEvent method, which is used to retrieve events returned from the query. The syntax is as follows:

set objEvents = objService.NextEvent([nDelay])

The optional nDelay parameter specifies how long to wait (in milliseconds) for an event before quitting. If the parameter is omitted, the NextEvent method will wait indefinitely for an event to be generated. The following script executes a notification query that fires events when new event log items are created:

Set objService = GetObject("winmgmts:{impersonationLevel=impersonate,(Security)")
Set objEvents = objService.ExecNotificationQuery _
("select * from __instancecreationevent where targetinstance isa "& _
 "'Win32_NTLogEvent'")

Set objEvent = objEvents.NextEvent()

The Win32_NTEventLog provider is known as an event provider. This means that it can "call back" to the originating program when an event is generated.

Providers that do not generate events require a WITHIN clause in the WQL statement. The WITHIN clause specifies a time delay for when the query is refreshed. The CIMV2 provider, which includes most of the informational Win32 and CIM classes discussed in this chapter, does not generate events and requires the WITHIN clause.

In the following script, an event fires whenever a new process starts on the remote machine Odin:




 

The following sample checks if the status of any NT service changes and displays the status of the service and the time a change occurred:

'svcstatus.vbs
'Description:monitors changes in service status
Option Explicit
Dim objService, objEvent, objEvents

Set objService = GetObject("winmgmts:{impersonationLevel=impersonate}")
'query for any changes in services every 60 seconds
Set objEvents = objService.ExecNotificationQuery _
 ("select * from __instancemodificationevent within 60 "& _
 "where targetinstance isa 'Win32_Service'")

WScript.Echo "Waiting for service change. . ."
Do
 Set objEvent = objEvents.Nextevent
 WScript.Echo objEvent.TargetInstance.Description & "state changed to "& _
 objEvent.TargetInstance.State & "at "& Now
Loop

See Also

Read the following WMI SDK documentation topics: "Object Creation and Monikers" and "SwbemServices and SWbemServices.ExecNotificationQuery Examples." For more information, read the MSDN Library article "Managing Windows with WMI" (http://msdn.microsoft.com/library/techart/mngwmi.htm).

Changing NT Service Account Information

Problem

You want to change the user ID and password for an NT service.

Solution

You can invoke the Change method for an instance of the Win32_Service class. This enables you to set the service for which you want to change the password.

'servicechng.vbs
'changes the password for all services with specific user ID
Dim objWMIObjects, objWMIObject, objServices, nResult
'get a reference to local WMI service
Set objServices = _
 GetObject("winmgmts:{impersonationLevel=impersonate}")
'get all services that use the Administrator account
Set objWMIObjects = objServices.ExecQuery( _
 "Select * From Win32_Service "& _
 Where StartName='Acme\Administrator'")

'loop through each service and change the password
For Each objWMIObject In objWMIObjects
 nResult = objWMIObject.Change(, , , , , , , "newpassword")
 If nResult = 0 Then
 WScript.Echo "Password successfully set for "& _
 objWMIObject.DisplayName
 Else
 WScript.Echo "Error setting password set for service "_
 & objWMIObject.DisplayName
 End If
Next

Discussion

Windows NT services can have either an NT service account or an NT account associated with them. If a user account is associated with the service, a password is required to be stored for the service.

When the passwords for an account are changed, they must be changed for the service to function properly. This can be a time-consuming process, especially if the account is used in services across multiple computers.

The WMI Win32_Service class exposes NT service information. The Change method can be used to change any service parameters. The syntax is as follows:

nResult = objWMIService.Change([Name],[DisplayName],[PathName] ,
[ServiceType],[StartMode],[DesktopInteract],[StartName],[StartPassword,]
[LoadOrderGroup],[LoadOrderGroupDependencies], [ServiceDependencies])

Table 10-12 lists the Change method's parameters.

Table 10-12: Change Method Parameters

PARAMETER

DESCRIPTION

Name

Internal service name used to reference service by WMI and ADSI.

DisplayName

Display name as it appears in service manager.

PathName

Path to service executable.

ServiceType

Integer value. 0 = Kernel, 1 = File System driver, 2 = Adapter, 3 = Recognizer driver, 4 = Process, and 5 = Win32 share process.

ErrorControl

Integer value. Indicates action taken by service manager if service fails to start. 0 = Ignore, 1 = Normal, 2 = Server, and 3 = Critical.

StartMode

Service start mode. Valid values are Boot, System, Automatic, Manual, or Disabled.

DesktopInteract

Boolean. If True, service can interact with desktop.

StartName

Account service runs under a DomainUsername format. If the service is logged on as LocalSystem, this value is set to Null.

StartPassword

Password for account.

LoadOrderGroup

Group name that service is associated with.

LoadOrderGroupDependencies

Array of service groups that service is dependent upon. These groups must start before the service starts.

ServiceDependencies

Array of services that service is dependent upon. These services must start before the service starts.

All parameters are optional. If you do not supply a specific parameter, the current setting is used. The method returns 0 if successful.

  Tip 

Do not make changes to service parameters unless you are absolutely sure of the effect of the change.

You can make individual references to services by querying the service with the Win32_Service value, which is the internal service's name:

Dim objService
'get a reference to the SQL Server service
Set objService = _
 GetObject("winmgmts:{impersonationLevel=impersonate}" & _
 "!Win32_Service.Name='MSSQLServer'")
'change the user ID and password for the service
 nResult = objWMIObject.Change(, , , , , , "AcmeSQLAdmin", "newpassword")

See Also

For more information, read the MSDN Library article "Win32_Service" (http://msdn.microsoft.com/library/en-us/wmisdk/r_32os5_4dyd.asp).



Managing Enterprise Systems with the Windows Script Host
Managing Enterprise Systems with the Windows Script Host
ISBN: 1893115674
EAN: 2147483647
Year: 2005
Pages: 242
Authors: Stein Borge

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net