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.
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.
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:
- Select Start menu > WMI SDK > WMI CIM Studio.
- The "Connect to namespace" dialog box appears, as shown in Figure 10-1.
Figure 10-1: Connect to namespace
Clicking the button
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.
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
Figure 10-3 shows the results of creating an instance of the Win32_ComputerSystem class from the WMI CIM Studio.
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.
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.
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.
Figure 10-4: Win32_OSRecoveryOption class details
Table 10-5 describes the 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.
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.
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.
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.
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
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.
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
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.
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.
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.
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).