3.3 Core OS components providers


3.3 Core OS components providers

3.3.1 The WBEM provider

The WBEM provider exposes the WMI configuration parameters. The three classes supported by this provider are listed in Table 3.1.

Table 3.1: The WBEM Provider Classes

Name

Type

Comments

Win32_WMISetting

Dynamic (Singleton)

Contains the operational parameters for the WMI service.

Win32_WMIEIementSetting

Association

Association between a service running in the Win32 system, and the WMI settings it can use.

Win32_MethodParameterClass

Abstract

Abstract, base class that implements method parameters derived from this class.

You can use the LoadCIMInXL.wsf script (see Sample 4.32 in the appendix) or the WMI CIM Studio of the Platform SDK to gather more information about the class properties. In the Platform SDK, these classes are classified as the WMI System Management classes.

The WBEM provider classes are available in the Root\CIMv2 namespace. Basically, the Win32_WMISetting class gives access to the WMI settings available from the WMI Control MMC (in the Computer Management MMC). Since there is one installation of WMI per system, there is only one instance of the Win32_WMISetting class. This is the reason why this class has no Key property defined in its properties and is therefore defined as a singleton class.

Because this class relates to one WMI installation in one system, the Win32_WMIElementSetting class associates the Win32_WMISetting with the Win32_Service class (see Figure 3.1). The Win32_WMISetting has one Windows associated service instance: the WinMgmt.Exe service.

click to expand
Figure 3.1: The Win32_WMISetting class associations.

The Win32_MethodParameterClass class is an abstract class, which means that no instance can be retrieved from the class. This class is used as a template for classes used as parameters when invoking specific methods. The Win32_MethodParameterClass is a superclass for the Win32_Security-Descriptor, Win32_ACE, Win32_Trustee, and Win32_ProcessStartup classes. For example, when executing the Create method of the Win32_Process class (see Sample 2.53 in Chapter 2), we create a Win32_ProcessStartup instance to define some process parameters used for its creation.

The WBEM provider is an instance provider only. If the Win32_WMISetting class must be used in the context of a WQL event query, the WITHIN statement must be used, because the provider is not implemented as an event provider. For example, a valid WQL query for the WBEM provider would be:

 Select * From __InstanceModificationEvent Within 10 Where TargetInstance ISA 'Win32_WMISetting' 

The WBEM instance provider supports the Get, Put, and Enumeration operations (see Table 3.2). This means that it is possible to retrieve a single instance (get) with its WMI object path, modify a single instance (put), and retrieve a collection of instances (enumeration).

Table 3.2: The WBEM Provider Capabilities

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

WBEM core Provider

WBEMCORE

Root/CIMV2

X

X

X

X

X

X

X

X

X

The next script sample is able to change some of the WMI settings from the command line. The WMI settings that can be changed are available from the script command-line help.

 C:\>WMISettings.wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMISettings.wsf /Action:value [/ASPScriptDefaultNamespace:value] [/ASPScriptEnabled[+|-]]                        [/BackupInterval:value] [/EnableEvents[+|-]] [/LoggingDirectory:value]                        [/LoggingLevel:value] [/MaxLogFileSize:value]                        [/Machine:value] [/User:value] [/Password:value] Options: Action                    : Specify the operation to perform: [List] or [Config]. ASPScriptDefaultNamespace : Defines the namespace used by calls from the scripting API if none is                             specified by the caller. ASPScriptEnabled          : Indicates whether WMI scripting can be used on Active Server Pages                             (ASP). This property is valid on Windows NT 4.0 systems only. BackupInterval            : Specifies the length of time that will elapse between backups of the WMI                             database. EnableEvents              : Indicates whether the WMI event subsystem should be enabled. LoggingDirectory          : Specifies the directory path containing the location of the WMI system                             log files. LoggingLevel              : Indicates whether event logging is enabled and the verbosity level of                             logging used. MaxLogFileSize            : Indicates the maximum size of the log files produced by the WMI service. Machine                   : Determine the WMI system to connect to. (default=LocalHost) User                      : Determine the UserID to perform the remote connection. (default=none) Password                  : Determine the password to perform the remote connection. (default=none) Examples:       WMISettings.wsf /Action:List       WMISettings.wsf /Action:Config /ASPScriptDefaultNamespace:Root\CIMv2       WMISettings.wsf /Action:Config /ASPScriptEnabled+       WMISettings.wsf /Action:Config /BackupInterval:30       WMISettings.wsf /Action:Config /EnableEvents+       WMISettings.wsf /Action:Config /LoggingDirectory:C:\WINDOWS\System32\Wbem\Logs       WMISettings.wsf /Action:Config /LoggingLevel:ErrorsOnly       WMISettings.wsf /Action:Config /MaxLogFileSize:65535 

The Win32_WMISetting class exposes more properties than the ones that can be modified by the script. However, this sample can be easily extended to cater to any additional WMI settings that need to be modified. The purpose of the script is to view the Win32_WMISetting singleton instance and update some of its properties. From a scripting technique point of view, there is nothing new compared with all scripts previously developed. The segment of code changing some WMI settings is shown in Sample 3.1.

Sample 3.1: Updating the WMI settings

start example

   1:<?xml version="1.0''?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  38:    </runtime>  39:  40:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs'' />  41:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  42:  43:    <object progobjWMILocator'' reference="true''/>  44:    <object progobjWMIDateTime'' />  45:  46:    <script language="VBscript">  47:    <![CDATA[  ..:  51:    Const cComputerName = "LocalHost"  52:    Const cWMINameSpace = "Root/cimv2"  53:    const cWMIClass = "Win32_WMISetting" 77:  ..:  77:    ' ----------------------------------------------------------------------------  78:    ' Parse the command line parameters  79:    If WScript.Arguments.Named.Count = 0 Then  80:       WScript.Arguments.ShowUsage()  81:       WScript.Quit  82:    End If ...: 131:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 132: 133:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 134:    objWMILocator.Security_.ImpersonationLevel = wbemlmpersonationLevellmpersonate 135: 136:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 137:                                                     strUserID, strPassword) ...: 140:    Set objWMIInstance = objWMIServices.Get (cWMIClass & "=(@") 143:    ' -- LIST -------------------------------------------------------------------- 144:    If boolList = True Then 145:       Set objWMIPropertySet = objWMIInstance.Properties_ 146:       For Each objWMIProperty In objWMIPropertySet 147:           DisplayFormattedProperty objWMIInstance, _ 148:                                    "  " & objWMIProperty.Name, _ 149:                                    objWMIProperty.Name, _ 150:                                    Null 151:        Next 152:        Set objWMIPropertySet = Nothing 153:        WScript.Echo 154:    End If 155: 156:    'CONFIG ---------------------------------------------------------------------- 157:    If boolConfig = True Then 158: 159:       If Len (strASPScriptDefaultNamespace) Then 160:          objWMIInstance.ASPScriptDefaultNamespace = StrASPScriptDefaultNamespace 161:       End If 162: 163:       If Len (boolASPScriptEnabled) Then 164:          objWMIInstance.ASPScriptEnabled = boolASPScriptEnabled 165:       End If 166: 167:       If intBackupInterval <> 0 Then 168:          objWMIInstance.BackupInterval = intBackupInterval 169:       End If 170: 171:       If Len (boolEnableEvents) Then 172:          objWMIInstance.EnableEvents = boolEnableEvents 173:       End If 174: 175:       If Len (strLoggingDirectory) Then 176:          objWMIInstance.LoggingDirectory = strLoggingDirectory 177:       End If 178: 179:       If longMaxLogFileSize <> 0 Then 180:          objWMIInstance.MaxLogFileSize = longMaxLogFileSize 181:       End If 182: 183:       If Len (strLoggingLevel) Then 184:          objWMIInstance.LoggingLevel = intLoggingLevel 185:       End If 186: 187:       objWMIInstance.Put_ (wbemChancFlagUpdateOnly Or _ 188:                            wbemFlagReturnWhenComplete) ...: 191:       WScript.Echo "WMI Settings updated." 192: 193:    End If ...: 199:    ]]> 200:    </script> 201:  </job> 202:</package> 

end example

As previously mentioned, the Win32_WMISetting class is a singleton class; this means that:

  • Only one instance is available per system.

  • There is no Key property.

Note that a particular syntax is used to create an instance of the Win32_ WMISetting singleton class (line 140). The WMI settings are updated from line 157 through 193. Only the specified settings are modified. Once the desired WMI properties are updated, the script commits the changes back to the system (lines 187 and 188).

The Sample 3.1 output obtained with the /Action:List switch is as follows:

  1:   C:\>WMISettings.wsf /Action:List  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   ASPScriptDefaultNamespace:  ...............Root\cimv2  6:   ASPScriptEnabled:  ........................TRUE  7:   AutorecoverMofs:  .........................J:\WINDOWS\system32\WBEM\cimwin32.mof  8:                                              J:\WINDOWS\system32\WBEM\cimwin32.mfl  9:                                              J:\WINDOWS\system32\WBEM\system.mof 10:                                              J:\WINDOWS\system32\WBEM\vmipcima.mof 11:                                              J:\WINDOWS\system32\WBEM\wmipcima.mfl ..: ..: ..: 62:                                              J:\WINDOWS\system32\WBEM\snmpsmir.mof 63:                                              J:\WINDOWS\system32\WBEM\snmpreg.mof 64:                                              J:\WINDOWS\System32\Wbem\RSoP.mof 65:                                              J:\WINDOWS\System32\Wbem\RSoP.mfl 66:                                              J:\WINDOWS\System32\Wbem\SceRsop.mof 67:                                              J: \WINDOWS\system32\wbem\iiswmi.mf1 68:                                              J: WINDOWS\systems32\wbem\ADStatus\TrustMon.mof 69:                                              J:\WINDOWS\System32\replprov.mof 70:   BackupInterval:  ..........................30 71:   BuildVersion:  ............................3663.0000 73:   EnableEvents:  ............................TRUE 74:   EnableStartupHeapPreallocation:  ..........FALSE 75:   HighThresholdOnClientObjects:  ............20000000 76:   HighThresholdOnEvents:  ...................20000000 77:   InstallationDiractory:  ...................J:\WINDOWS\system32\WBEM 78:   LoggingLevel:  ............................J: WINDOWS\system32\WBEM\Logs\ 79:   LoggingLevel: .............................1 80:   LowThresholdOnClientObjects:  .............10000000 81:   LowThresholdOnEvents:  ....................10000000 82:   MaxLogFileSize:  ..........................65536 83:   MaxWaitOnClientObjects:  ..................60000 84:   MaxWaitOnEvents:  .........................2000 85:   MofSelfInstallDirectory:  .................J: WINDOWS\system32\WBEM\MOF 

Among this list of properties, the output shows the list of MOF files to recompile when recovering the CIM repository (lines 7 through 69), the backup interval (line 70), and the WMI logging level (line 79).

3.3.2 NT Event Log providers

The NT Event Log providers consist of two WMI providers: one WMI event provider and one instance and method provider, which support the get, put, and enumeration operations (see Table 3.3).

Table 3.3: The NT Event Log Providers Capabilities

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Profesional

Windows NT 4.0

Event Log Providers

MS_NT_EVENTLOG_EVENT_PROVIDER

Root/CIMV2

X

X

X

X

X

X

MS_NT_EVENTLOG_PROVIDER

Root/CIMV2

X

X

X

X

X

X

X

X

X

X

These providers are designed to expose information stored in the Windows NT Event Log files, view the configuration settings related to the Windows NT Event Log files, and perform some specific actions, such as clearing or backing up the NT Event Log. The classes supported by these providers are listed in Table 3.4.

Table 3.4: The NT Event Log Providers Classes

Name

Type

Comments

Win32_NTEventlogFile

Dynamic

Represents settings of a Windows NT/Windows 2000 Event Log file

Win32_NTLogEvent

Dynamic

Represents data stored in a Windows NT/Windows 2000 log file.

Win32_NTLogEventComputer

Association

Relates instances of Win32_NTLogEvent and Win32_ComputerSystem.

Win32_NTLogEventLog

Association

Relates instances of Win32_NTLogEvent and Win32_NTEventlogFile classes.

Win32_NTLogEventUser

Association

Relates instances of Win32_NTLogEvent and Win32 UserAccount.

These classes are available in the Root\CIMv2 namespace. The Win32_ NTLogEvent class is shown in Figure 3.2.

click to expand
Figure 3.2: The Win32_NTLogEvent associations.

Since there is an NT Event Log event provider, there is no need to use the WITHIN statement in a WQL event query. In such a case, a valid WQL query would be as follows:

  • To capture any WMI event corresponding to a record addition to any NT Event Log:

     Select * From __InstanceCreationEvent Where TargetInstance ISA  Win32_NTLogEvent 

  • To capture any WMI event corresponding to a record addition to the Directory Service Event Log:

     Select * From __InstanceCreationEvent Where TargetInstance ISA  Win32_NTLogEvent' And TargetInstance.LogFile='Directory Service''' 

It is important to note that the NT Event Log event provider only supports the intrinsic event __InstanceCreationEvent class. The generic asynchronous script to capture events from a WQL event query passed on the command line (see Sample 6.17, "A generic script for asynchronous event notification" in the appendix) can be used with the following command line. The output will be as follows when a new Event Log record is created:

  1:   C:\>GenericEventAsyncConsumer.wsf "Select * From __InstanceCreationEvent  2:                                               Where TargetInstance ISA 'Win32_NTLogEvent'  And  3:                                               TargetInstance.EventCode=1013"  4:   Microsoft (R) Windows Script Host Version 5.6  5:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  6:  7:   Waiting for events...  8:  9:   BEGIN - OnObjectReady. 10:   Sunday, 11 November, 2001 at 16:51:01: '__InstanceCreationEvent' has been triggered. 11: 12:     - __InstanceCreationEvent --------------------------------------------------- 13:     SECURITY_DESCRIPTOR: ................... 1,0,4,128,84,1,0,0,96,1,0,0,0,0,0,0,20,... 14: 15:       - Win32_NTLogEvent -------------------------------------------------------- 16:       Category: ............................ 1 17:       CategoryString: ...................... Knowledge Consistency Checker 18:       ComputerName: ........................ NET-DPEN6400A 19:       EventCode: ........................... 1013 20:       EventIdentifier: ..................... 1073742837 21:       EventType: ........................... 3 22:       *Logfile: ............................ Directory Service 23:       Message:. ............................ Internal event: The replication topology ... 24:       *RecordNumber: ....................... 72 25:       SourceName: .......................... NTDS KCC 26:       TimeGenerated: ....................... 11-11-2001 16:50:39 27:       TimeWritten: ......................... 11-11-2001 16:50:39 28:       Type: ................................ information 29:       User: ................................ NT AUTHORITY\ANONYMOUS LOGIN 30: 31:     TIME_CREATED: .......................... 11-11-200115:50:40 (20011111145040.276894+060) 32 33:   END - OnObjectReady. 34: 35:   Cancelling event subscription ... 36: 37:   BEGIN - OnCompleted. 38:   END   - OnCompleted. 39:   Finished. 

The second interesting class supported by the NT Event Log providers is the Win32_NTEventlogFile class. In addition to being able to review and configure various NT Event Log configuration settings (i.e., Maximum Size, overwrite policy) you can also clear and back up any NT Event Log. The next script sample illustrates how to achieve this. Its command-line parameters are as follows:

 C:\>WMIEventLog.Wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIEventLog.wsf /Action:value [/EventLog:value] [/MaxFileSize:value]                        [/OverwriteOutDated:value] [/Machine:value] [/User:value] [/Password:value] Options: Action :          : Specify the operation to perform: [List], [Config], [Clear] and [Backup]. EventLog          : Specify the Log name (All means all available Event Logs). MaxFileSize       : Set the maximum size of the Event Log file (in Kb). OverwriteOutDated : Overwrites events policy [WhenNeeded], [Never] or a value 1 and 365. Machine      : Determine the WMI system to connect to. (default=LocalHost) User              : Determine the UserID to perform the remote connection. (default=none) Password          : Determine the password to perform the remote connection. (default=none) Examples:       WMIEventLog.wsf /Action:List       WMIEventLog.wsf /Action:Clear /EventLog:All       WMIEventLog.wsf /Action:Clear /EventLog:NTDS       WMlEventLog.wsf /Action:Backup /EventLog:DNSEvent       WMIEventLog.wsf /Action:Backup /EventLog:NTFRS       WMIEventLog.wsf /Action:Config /EventLog:SecEvent /MaxFilsSize:5120       WMIEventLog.wsf /Action:Config /EventLog:SysEvent /OverwriteOutDated:7       WMIEventLog.wsf /Action:Config /EventLog:All /OverwriteOutDated:WhenNeeded       WMIEventLog.wsf /Action:Config /EventLog:AppEvent /OverwriteOutDated:Never       WMIEventLog.wsf /Action: Config /EventLog:All /MaxFileSize:5120 /OverwriteOutDated:WhenNeeded 

The script code using the Win32_NTEventLogFile class capabilities is shown in Sample 3.2. As usual, the script uses the same structure to define (skipped lines 13 through 35) and parse the command-line parameters (skipped lines 78 through 142) and to list the instance properties available from this class (lines 159 through 173).

Sample 3.2: Viewing and updating the NT Event Log configuration and clearing and backing up the NT Event Log information

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  35:    </runtime>  36:  37:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" />  38:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  39:  40:    <object prog  reference="true"/>  41:    <object prog  />  42:  43:    <script language="VBscript">  44:    <![CDATA[  ..:  48:    Const cComputerName = "LocalHost"  49:    Const cWMINameSpace = "Root/cimv2"  50:    Const cWMIClass = "Win32_NTEventLogFile"  ..:  77:    ' -----------------------------------------------------------------------------  78:    ' Parse the command line parameters  79:    If WScript.Arguments.Named.Count = 0 Then  80:       WScript.Arguments.ShowUsage()  81:       WScript.Quit  82:    Else  83:       Select Case Ucase(WScript.Arguments.Named("Action"))  ..:  96:       End Select  97:    End If ...: 116:    If Len(strOverWriteOutDated) Then 117:       Select Case Ucase (strOverWriteOutDated) 118:              Case "WHENNEEDED" 119:                   intOverWriteOutDated = 0 120:                   strOverWriteOutDated = "WhenNeeded" 121:              Case "NEVER" 122:                   intOverWriteOutDated = 4294967295       ' 2^32 - 1 123:                   strOverWriteOutDated = "Never" 124:              Case Else 125:                   intOverWriteOutDated = Cint (strOverWriteOutDated) 126:                   If intOverWriteOutDated < 1 Or intOverWriteOutDated > 365 Then 127:                      WScript.Echo "Invalid overwrite outdated parameter." & vbCRLF 128:                      WScript.Arguments.ShowUsage() 129:                      WScript.Quit 130:                   End If 131:                   strOverWriteOutDated = "OutDated" 132:       End Select 133:    End If ...: 142:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 143: 144:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 145:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 146:    objWMILocator.Security_.Privileges.AddAsString "SeBackupPrivilege", True 147:    objWMILocator.Security_.Privileges.AddAsString "SeSecurityPrivilege", True 148: 149:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 150:                                                     strUserID, strPassword) ...: 153:    Set objWMIInstances = objWMIServices.InstancesOf (cWMIClass, wbemFlagUseAmendedQualifiers) ...: 156:    For Each objWMIInstance in objWMIInstances 157: 158:        ' -- LIST --------------------------------------------------------------------------- 159:        If boolList = True Then 160:           WScript.Echo "- " & objWMIInstance.LogfileName & " Event Log " & _ 161:                        "(" & Ucase (objWMIInstance.FileName) & _ 162:                        ") " & String (60, "-") 163: 164:           Set objWMIPropertySet = objWMIInstance.Properties_ 165:           For Each objWMIProperty In objWMIPropertySet 166:               DisplayFormattedProperty objWMIInstance, _ 167:                                        " " & objWMIProperty.Name, _ 168:                                        objWMIProperty.Name, _ 169:                                        Null 170:           Next 171:           Set objWMIPropertySet = Nothing 172:           WScript.Echo 173:        End If 174: 175:        If UCase (objWMIInstance.FileName) = strEventLogName Or _ 176:           strEventLogName = "ALL" Then 177:           ' -- CONFIG ----------------------------------------------------------------------- 178:           If boolConfig = True Then 179: 180:           If intMaxFileSize <> 0 Then 181:              objWMIInstance.MaxFileSize = intMaxFileSize * 1024 182:           End If 183: 184:           If Len (strOverWriteOutDated) Then 185:              objWMIInstance.OverwriteOutDated = intOverWriteOutDated 186:              objWMIInstance.OverWritePolicy = strOverWriteOutDated 187:           End If 188: 189:           objWMIInstance.Put_ (wbemChangeFlagUpdateOnly Or _ 190:                                wbemFlagReturnWhenComplete Or _ 191:                                wbemFlagUseAmendedQualifiers) 192:           If Err.Number Then ErrorHandler (Err) 193: 194:           If intMaxFileSize <> 0 Then 195:              varTemp = objWMIInstance.LogfileName & _ 196:                        " Event Log maximum size is set on " & _ 197:                        intMaxFileSize & " Kb. " 198:           Else 199:              varTemp = objWMIInstance.LogfileName & _ 200:                        " Event Log overwrite policy configured. " 201:           End If 202: 203:           Select Case Ucase (strOverWriteOutDated) 204:                  Case "WHENNEEDED" 205:                       WScript.Echo varTemp & "Events are overwritten as needed." 206:                  Case "NEVER" 207:                       WScript.Echo varTemp & "Events are never overwritten." 208:                  Case "OUTDATED" 209:                       WScript.Echo varTemp & "Events older than " & _ 210:                                    intOverWriteOutDated & _ 211:                                    " day(s) are overwritten." 212:                  Case Else 213:                       WScript.Echo varTemp 214:           End Select ...: 217:        End If 218: 219:        ' -- CLEAR ------------------------------------------------------------------------- 220:        If boolClear = True Then 221:           intRC = objWMIInstance.ClearEventlog 222:           If Err.Number Then ErrorHandler (Err) 223: 224:           WScript.Echo objWMIInstance.LogfileName & _ 225:                        " Event Log is cleared (" & intRC & ")." ...: 228:        End If 229: 230:        ' -- BACKUP ----------------------------------------------------------------------- 231:        If boolBackup = True Then 232:           intRC = objWMIInstance.BackupEventlog (objWMIInstance.Name & ".Bak") 233:           If Err.Number Then ErrorHandler (Err) 234: 235:           WScript.Echo objWMIInstance.LogfileName & " Event Log is backuped to '" & _ 236:                        Ucase (objWMIInstance.Name) & ".Bak' (" & intRC & ")." ...: 239:           End If 240: 241:       End If 242:    Next ...: 248:     ]]> 249:     </script> 250:   </job> 251:</package> 

end example

The most interesting part of this script resides in the NT Event Log settings configuration (lines 178 through 217) and the method invocations (lines 220 through 228 for clearing and lines 231 through 239 for backup). The script is structured in such a way that it can manage all NT Event Logs in one single run. For this, the script gets the collection of all NT Event Logs available (line 153) and performs an enumeration (lines 156 through 242). Then, the script uses a special NT Event Log name called "All" (as defined in the script at line 176) to determine if the operation concerns a specific NT Event Log name or all the collection (lines 175 and 176). This script uses the "All" label to differentiate the scope of the requested operation.

An interesting NT Event Log setting is the overwrite policy. To set the overwrite policy (lines 185 and 186) two properties of the NT Event Log instance must be set up. The two property values are determined during the command-line parameters parsing (lines 117 through 132). The command-line parsing for this setting ensures that correct values are set. It is important to note that both property values must be set up as shown in Table 3.5.

Table 3.5: The OverWritePolicy and OverwriteOutDated Property Values

WhenNeeded

Never

OutDated

OverWritePolicy

0

4294967295

1 < Value > 365

OverwriteOutDated

WhenNeeded

Never

OutDated

Last but not least, some privileges at the WMI level must be specified (lines 146 and 147) to ensure transparent access to the Security NT Event Log (line 146) and perform the backup operation (line 147).

3.3.3 Registry providers

There are three WMI providers in this category: one instance and method provider (RegProv), one property provider (RegPropProv), and one event provider (RegistryEventProvider). The providers capabilities are summarized in Table 3.6.

Table 3.6: The Registry Providers Capabilities

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

Rigistry Providers

RegistryEventProvider

Root/DEFAULT

X

X

X

X

X

X

ReProProv

Root/DEFAULT

X

X

X

X

X

X

X

X

RegProv

Root/DEFAULT

X

X

X

X

X

X

X

X

X

X

These providers are designed to expose information stored in the Windows NT Registry. The classes supported by these providers are listed in Table 3.7.

Table 3.7: The Registry Providers Classes

Name

Type

Comments

StdRegProv

Dynamic

The StdRegProv class only contains methods that interact with the system registry. You can use these methods to verify the access permissions for a user, create, enumerate, and delete registry keys; create, enumerate, and delete named values; and read, write, and delete data values.

RegistryValueChangeEvent

Extrinsic event

Represents a registry extrinsic event that corresponds to a registry value modification.

RegistryKeyChangeEvent

Extrinsic event

Represents a registry extrinsic event that corresponds to a registry key modification.

RegistryTreeChangeEvent

Extrinsic event

Represents a registry extrinsic event that corresponds to a registry tree modification.

These classes are available in the Root\Default namespace. The StdRegProv class only exposes methods; it does not expose any property and has no association.

The Registry event provider allows a process to receive a notification when a registry change occurs. For this, three extrinsic event classes are supported (see Table 3.7). Each of these classes corresponds to a particular modification made in the registry. For example, imagine that you would like to monitor the registry key value that enables Active Directory schema changes. The key value is named "Schema Update Allowed" and is located in the following registry key hive:

 HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Parameters 

To detect any change made on that key value, the following WQL event query must be used:

 Select * FROM RegistryValueChangeEvent Where Hive='HKEY_LOCAL_MACHINE' AND               KeyPath='SYSTEM\\CurrentControlSet\\Services\\NTDS\\Parameters' AND               ValueName='Schema Update Allowed' 

Now, if you want to detect all changes made to any key values below the same registry key hive, the following WQL Event query must be used:

 Select * FROM RegistryKeyChangeEvent Where Hive='HKEY_LOCAL_MACHINE'  AND               KeyPath='SYSTEMX\CurrentControlSet\\Services\\NTDS\\Parameters 

If you want to detect all changes made to any key values under the following registry key hive and all child registry entries, use the following:

 HKLM\SYSTEM\CurrentControlSet\Services\NTDS 

The following WQL event query must be used:

 Select * FROM RegistryTreeChangeEvent Where Hive='HKEY_LOCAL_MACHINE' AND               RootPath='SYSTEM\\CurrentControlSet\\Services\\NTDS' 

To summarize:

  • The extrinsic Registry ValueChangeEvent class focuses the change detection on a particular key value.

  • The extrinsic RegistryKeyChangeEvent class focuses the change detection on all key values below a given registry key hive.

  • The extrinsic RegistryTreeChangeEvent class focuses the change detection on all key values in a given registry key hive, as shown in the example below.

If we reuse the generic asynchronous script to capture events from a WQL event query (see Sample 6.17, "A generic script for asynchronous event notification" in the appendix) with the last WQL Event query sample, the output will be as follows:

  1:   C:\>GenericEventAsyncConsumer.wsf "Select * FROM RegistryTreeChangeEvent Where  2:                                     Hive=HKEY_LOCAL_MACHINE' AND  3:                                     RootPath='SYSTEM\\CurrentControlSet\\Services\\NTDS'"  4:                                     /NameSpace:Root\Default  5:   Microsoft (R) Windows Script Host Version 5.6  6:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  7:  8:   Waiting for events...  9: 10:   BEGIN - OnObjectReady. 11:   Monday, 19 November, 2001 at 13:27:29: 'RegistryTreeChangeEvent' has been triggered. 12: 13:     - RegistryTreeChangeEvent ------------------------------------------------------- 14:     Hive: .................................. HKEY_LOCAL_MACHINE 15:     RootPath: .............................. SYSTEM\CurrentControlSet\Services\NTDS 16:     TIME_CREATED: .......................... 19-11-2001 12:27:29 (20011119112729.796836+060) 17: 18:   END - OnObjectReady. 

Even if we get a notification, it is important to note that we do not get the registry value associated with the change in the instance representing the notification.

Besides the registry key monitoring, the methods exposed by the StdReg-Prov class allow the enumeration of registry keys and values. It is also possible to create new registry keys, read and update registry key values, and delete registry keys and values. These methods are summarized in Table 3.8.

Table 3.8: The StdRegProv Methods

Method name

DeSetStringValue

CheckAccess

Verifies that the user possesses the specified access permissions.

CreateKey

Creates a subkey.

DeleteKey

Deletes a subkey.

DeleteValue

Deletes a named value.

EnumKey

Enumerates subkeys.

EnumValues

Enumerates the named values of a key.

GetBinaryValue

Gets the binary data value of a named value.

GetDWORDValue

Gets the DWORD data value of a named value.

GetExpandedStringValue

Gets the expanded string data value of a named value.

GetMultiStringValue

Gets the multiple string data values of a named value.

GetStringValue

Gets the string data value of a named value.

SetBinaryValue

Sets the binary data value of a named value.

SetDWORDValue

Sets the DWORD data value of a named value.

SetExpandedStringValue

Sets the expanded string data value of a named value.

SetMultiStringValue

Sets the multiple string values of a named value.

SetStringValue

Sets the string value of a named value.

Sample 3.3 illustrates the use of these methods. Its command-line parameters are as follows:

 C:\>WMIRegistry Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIRegistry.wsf [RegistryKeyValue] /BaseKey:value /Action:value [/DisplayRegValues[+|-]]                                           [/KeyType:value] [/SearchString:value]                                           [/ReplaceString:value] [/Machine:value]                                           [/User:value] [/Password:value] Options: RegistryKeyValue : The registry key name with its value. BaseKey          : Specify the base registry. Action           : Specify the operation to perform: [list], [Search], [Replace], [create], [update] or [delete]. DisplayRegValues : Display the registry key values (default=TRUE) KeyType          : Specify the registry value type. SearchString     : String to search in the registry. ReplaceString    : String to replace in the registry. Machine          : Determine the WMI system to connect to. (default=LocalHost) User             : Determine the UserID to perform the remote connection. (default=none) Password         : Determine the password to perform the remote connection. (default=none) Examples: WMIRegistry.wsf /BaseKey:HKLM\Software\MyKeys /Action:Create WMIRegistry.wsf MyStringValue=XYW /KeyType:REG_SZ /BaseKey:HKLM\Software\MyKeys /Action:Create WMIRegistry.wsf MyMultiStringValue=RST,STU,TUV,UVW,VWX,WXY,XYZ /KeyType:REG_MULTI_SZ                 /BaseKey:HKLM\Software\MyKeys /Action:Create WMIRegistry.wsf MyExpandedStringValue=%SystemRoot%\System32\Wbem /KeyType:REG_EXPAND_SZ                 /BaseKey:HKLM\Software\MyKeys /Action:Create WMIRegistry.wsf MyDWordValue=436327632 /KeyType:REG_DWORD                 /BaseKey:HKLM\Software\MyKeys /Action:Create WMIRegistry.wsf MyBinaryValue=03,04,255,78,34,23 /KeyType:REG_BINARY                 /BaseKey:HKLM\Software\MyKeys /Action:Create WMIRegistry.wsf /BaseKey:HKLM\Software /Action:List /DisplayRegValues- WMIRegistry.wsf /BaseKey:HKLM\Software /Action:List /DisplayRegValues+ WMIRegistry.wsf /BaseKey:HKLM\SOFTWARE\MyKeys /Action:Search /SearchString:String WMIRegistry.wsf /BaseKey:HKLM\SOFTWARE\MyKeys /Action:Replace                 /SearchString:String /ReplaceString:MyString WMIRegistry.wsf MyBinaryValue /BaseKey:HKLM\Software\MyKeys /Action:Delete WMIRegistry.wsf /BaseKey:HKLM\Software\MyKeys /Action:Delete 

Sample 3.3: Browsing, creating, deleting, searching, and replacing information in the registry (Parti)

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  42:    </runtime>  43:  44:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\SearchStringFunction.vbs" />  45:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\ReplaceStringFunction.vbs" />  46:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\ConvertStringInArrayFunction.vbs" />  47:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\ConvertArrayInStringFunction.vbs" />  48:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  49:  50:    <object prog  reference="true"/>  51:  52:    <script language="VBscript">  53:    <![CDATA[  ..:  57:    Const cComputerName = "LocalHost"  58:    Const cWMINameSpace = "Root/default"  59:    Const cWMIClass = "StdRegProv"  60:  61:    Const HKEY_CLASSES_ROOT = &h80000000  62:    Const HKEY_CURRENT_USER = &h80000001  63:    Const HKEY_LOCAL_MACHINE = &h80000002  64:    Const HKEY_USERS = &h80000003  65:    Const HKEY_CURRENT_CONFIG = &h80000005  66:    Const HKEY_DYN_DATA = &h80000006  67:  68:    Const REG_SZ = 1  69:    Const REG_EXPAND_SZ = 2  70:    Const REG_BINARY = 3  71:    Const REG_DWORD = 4  72:    Const REG_MULTI_SZ = 7  73:  74:    Const cBrowse = 0  75:    Const cSearch = 1  76:    Const cReplace = 2 ...: 109:    ' -------------------------------------------------------------------------------- 110:    ' Parse the command line parameters 111:    If WScript.Arguments.Named.Count = 0 Then 112:       WScript.Arguments.ShowUsage() 113:       WScript.Quit 114:    End If 115: 116:    If WScript.Arguments.Named.Count Then 117:       Select Case Ucase(WScript.Arguments.Named("Action")) 118:              Case "LIST" 119:                   boolList = True 120:                   intBrowseLevel = cBrowse 121:              Case "SEARCH" 122:                   boolList = True 123:                   intBrowseLevel = cSearch 124:              Case "REPLACE" 125:                   boolList = True 126:                   intBrowseLevel = cReplace 127:              Case "CREATE" 128:                   boolCreate = True 129:              Case "DELETE" 130:                   boolDelete = True 131:              Case Else 132:                   WScript.Echo "Invalid action type. Only [List], [Search], ..." & vbCRLF 133:                   WScript.Arguments.ShowUsage() 134:                   WScript.Quit 135:       End Select 136: 137:       strBaseKey = WScript.Arguments.Named("BaseKey") 138:       If Len(strBaseKey) = 0 Then 139:          WScript.Echo "Invalid registry key path." & vbCRLF 140:          WScript.Arguments.ShowUsage() 141:          WScript.Quit 142:       Else 143:          intDelimiterPosition = InStr (strBaseKey, "\") 144:          If intDelimiterPosition Then 145:             strHiveType = Mid (strBaseKey, 1, intDelimiterPosition - 1) 146:             strBaseKey = Mid (strBaseKey, intDelimiterPosition + 1) 147:          Else 148:             If boolList Then 149:                strHiveType = strBaseKey 150:                strBaseKey = "" 151:             Else 152:                WScript.Echo "Invalid registry key base." & vbCRLF 153:                WScript.Arguments.ShowUsage() 154:                WScript.Quit 155:             End If 156:          End If 157: 158:          Select Case Ucase (strHiveType) 159:                 Case "HKCLS" 160:                      intHiveType = HKEY_CLASSES_ROOT 161:                 Case "HKCU" 162:                      intHiveType = HKEY_CURRENT_USER 163:                 Case "HKLM" 164:                      intHiveType = HKEY_LOCAL_MACHINE 165:                 Case "HKUSERS" 166:                      intHiveType = HKEY_USERS 167:                 Case "HKCONFIG" 168:                      intHiveType = HKEY_CURRENT_CONFIG 169:                 Case "HKDYN" 170:                      intHiveType = HKEY_DYN_DATA 171:                 Case Else 172:                      WScript.Echo "Invalid hive type. Only [HKCLS], [HKCU], ..." & vbCRLF 173:                      WScript.Arguments.ShowUsage() 174:                      WScript.Quit 175:          End Select 176:       End If 177:    End If 178: 179:    If WScript.Arguments.Unnamed.Count = 1 Then 180:       strKeyName = WScript.Arguments.Unnamed.Item(0) 181:       intDelimiterPosition = InStr (strKeyName, "=") 182:       If intDelimiterPosition Then 183:          varKeyNameValue = Mid (strKeyName, intDelimiterPosition + 1) 184:          strKeyName = Mid (strKeyName, 1, intDelimiterPosition - 1) 185:       Else 186:          If Not boolDelete = True Then 187:             WScript.Echo "Invalid registry key value." & vbCRLF 188:             WScript.Arguments.ShowUsage() 189:             WScript.Quit 190:          End If 191:       End If 192:       If boolDelete = False Then 193:          Select Case Ucase (WScript.Arguments.Named("KeyType")) 194:                 Case "REG_SZ" 195:                      intKeyType = REG_SZ 196:                      boolKeyValue = True 197:                 Case "REG_MULTI_SZ" 198:                      varKeyNameValue = ConvertStringInArray (varKeyNameValue, ",") 199:                      intKeyType = REG_MULTI_SZ 200:                      boolKeyValue = True 201:                 Case "REG_EXPAND_SZ" 202:                      intKeyType = REG_EXPAND_SZ 203:                      boolKeyValue = True 204:                 Case "REG_BINARY" 205:                      varKeyNameValue = ConvertStringInArray (varKeyNameValue, ",") 206:                      intKeyType = REG_BINARY 207:                      boolKeyValue = True 208:                 Case "REG_DWORD" 209:                      varKeyNameValue = CLng (varKeyNameValue) 210:                      intKeyType = REG_DWORD 211:                      boolKeyValue = True 212:                 Case Else 213:                      WScript.Echo "Invalid key type. Only [REG_SZ], ..." & vbCRLF 214:                      WScript.Arguments.ShowUsage() 215:                      WScript.Quit 216:          End Select 217:       End If 218:    End If 219: 220:    strStringToSearch = WScript.Arguments.Named("SearchString") 221:    If Len(strStringToSearch) = 0 And intBrowseLevel = 1 Then 222:       WScript.Echo "Invalid search string." 223:       WScript.Arguments.ShowUsage() 224:       WScript.Quit 225:    End If 226: 227:    strStringToReplace = WScript.Arguments.Named("ReplaceString") 228:    If Len(strStringToSearch) = 0 And Len(strStringToReplace) = 0 And intBrowseLevel = 2 Then 229:       WScript.Echo "Invalid search or replace string." 230:       WScript.Arguments.ShowUsage() 231:       WScript.Quit 232:    End If 233: 234:    If intBrowseLevel = 0 Then boolDisplayRegValues=WScript.Arguments.Named("DisplayRegValues") 235:    If Len(boolDisplayRegValues) = 0 Then boolDisplayRegValues = True 236: 237:    strUserID = WScript.Arguments.Named("User") 238:    If Len(strUserID) = 0 Then strUserID = "" 239: 240:    strPassword = WScript.Arguments.Named("Password") 241:    If Len(strPassword) = 0 Then strPassword = "" 242: 243:    strComputerName = WScript.Arguments.Named("Machine") 244:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 245: 246:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 247:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 248: 249:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 250:                                                     strUserID, strPassword) ...: 253:    Set objWMIClass = objWMIServices.Get (cWMIClass) ...: 255: ...: ...: ...: 

end example

With this script it is possible to manage the Windows registry from the command line. Other than simply browsing or updating the registry, it is also capable of performing search and replace operations in the registry. This script is shown in Samples 3.3 through 3.9. Careful use of the replace feature is recommended, since it is very easy to mess up a working system!

To perform the command-line definition (skipped lines 13 through 42) and parsing (lines 111 through 244), the script reuses the same structure as seen in the previous script samples. Next, it reuses most of the functions previously developed (lines 46 through 48). Only two new functions, SearchString() (line 44) and ReplaceString() (line 45), are added to support the search and replace capabilities. We will come back to the use of these functions later, along with the script discovery (see Samples 3.3 through 3.9).

Some very important constants are also defined in the script header. These constants are used to identify the registry hive type (lines 61 through 66) and the registry key value type (lines 68 through 72). These constants will be used later in the script.

Before diving into the code, it is important to note that the logic used for the search and replace capabilities is a particular case of the script logic used to browse the registry. We will see this further, but this peculiarity is reflected during the command-line parameter parsing (lines 117 through 135) where the "List," "Search," and "Replace" actions define a different browse level value (List=0, Search= 1, Replace=2).

From line 137 through 176, the script parses the /BaseKey switch. Basically, it separates the complete registry key path given on the command line into two parts: the registry hive (i.e., HKLM) and the tree path (i.e., SOFTWARE\Microsoft). The registry hive is converted to its corresponding value (lines 158 through 175) based on the constants given in the script header. This value is required for the methods exposed by the StdRegProv class.

Lines 179 through 218 parse the registry key name (line 183), its value assignment (line 184), and its type (lines 193 through 216). The logic developed is very similar to the one used to parse the environment variable assignment developed in the previous chapter (see Sample 2.26, "Reading, creating, updating, and deleting environment variables").

After establishing the WMI connection (lines 249 and 250), the StdRegProv class is instantiated. Note that a class instance is created (line 253), since the StdRegProv class is defined as a static class (Static qualifier).

Based on the command-line parameters, the browse operation is started in Sample 3.4. There is nothing unusual in this piece of code, since the browsing logic is encapsulated in a subfunction (line 261).

Sample 3.4: Browsing information in the registry (Part II)

start example

 ...: ...: ...: 255: 256:    ' -- LIST --------------------------------------------------------------------------- 257:    If boolList = True Then 258:       intCounterValue = 0 259:       intCounterValueName = 0 260: 261:       BrowseRegistry objWMIClass, intHiveType, strBaseKey 262: 263:       Select Case intBrowseLevel 264:              Case cBrowse 265: 266:              Case csearch 267:                   WScript.Echo 268:                   WScript.Echo intCounterValue & " registry value(s) found." 269:                   WScript.Echo intCounterValueName & " registry value name(s) found." 270:              Case cReplace 271:                   WScript.Echo 272:                   WScript.Echo intCounterValue & " registry value(s) replaced." 273:                   WScript.Echo intCounterValueName & " registry value name(s) replaced." 274:       End Select 275: 276:       WScript.Echo vbCRLF & "Completed." 277: 278:    End If 279: ...: ...: ...: 

end example

Once the browse operation completes, and based on the browse type (simply browsing, searching, or replacing), an output message is displayed to show the number of matches during a search (lines 268 and 269) or a replace (lines 272 and 273). We will examine the BrowseRegistry() function in Samples 3.7 and 3.8.

To create registry information (see Sample 3.5), two different cases must be considered:

  • The registry tree is already created and a registry key value must be created: This case corresponds to the logic coded from line 282 through 292. This portion of code sets the registry key value. If the key exists, it is updated; if the key does not exist, it is created. The key value creation or update is encapsulated in the SetRegistryValue() function (line 283). This operation is encapsulated in a subfunction, because a particular StdRegProv class method must be invoked based on the registry key type (i.e., REG_SZ, REG_DWORD). This function will also be reused during the replace operation. This case corresponds to the following command-line parameters:

     C:\>WMIRegistry.wsf MyStringValue=XYW /KeyType:REG_SZ /BaseKey:HKLM\Software\MyKeys /Action:Create 

  • The registry tree does not exist and it must be created: This case corresponds to the logic coded from line 294 through 299. This portion of code creates a registry tree by using the CreateKey method exposed by the StdRegProv class (line 294). This piece of code is only executed when no registry key assignment is given on the command line (line 282). This case corresponds to the following command-line parameters:

     C:\>WMIRegistry.wsf /BaseKey:HKLM\Software\MyKeys /Action:Create 

Sample 3.5: Creating information in the registry (Part III)

start example

 ...: ...: ...: 279: 280:    ' -- CREATE ------------------------------------------------------------------------- 281:    If boolCreate = True Then 282:       If boolKeyValue Then 283:          intRC = SetRegistryValue (objWMIClass, intHiveType, _ 284:                                    strBaseKey, intKeyType, _ 285:                                    strKeyName, varKeyNameValue) 286:          If intRC Then 287:             WScript.Echo "Cannot create registry key value '" & strKeyName & _ 288:                          "' under '" & strBaseKey & "' (" & intRC & ")." 289:          Else 290:             WScript.Echo "Registry key value '" & strKeyName & "' under '" & _ 291:                          strBaseKey & "' created." 292:          End If 293:       Else 294:          intRC = objWMIClass.CreateKey(intHiveType, strBaseKey) 295:          If intRC Then 296:             WScript.Echo "Cannot create registry key '" & strBaseKey & "' (" & intRC & ")." 297:          Else 298:             WScript.Echo "Registry key '" & strBaseKey & "' created." 299:          End If 300:       End If 301:    End If 302: ...: ...: ...: 

end example

To delete some registry data (see Sample 3.6), two different cases must be considered:

  • A registry value must be deleted: This case corresponds to the logic coded from line 305 through 313. This portion of code deletes the registry value by using the DeleteValue method exposed by the StdReg-Prov class (line 306). This piece of code is only executed when registry key name is given on the command line (line 305). This corresponds to the following command-line parameters:

     C:\>WMIRegistry.wsf MyStringValue /EaseKey:HKLM\Software\MyKeys /Action:Delete 

  • A registry key must be deleted: This case corresponds to the logic coded from line 315 through 321. This portion of code deletes the registry key by using the DeleteKey method exposed by the StdRegProv class (line 315). Note that it is not possible to delete a complete registry tree with this method. If subkeys exist below the selected registry key, they must be deleted first. This piece of code is only executed when no registry key name is given on the command line (line 305). This case corresponds to the following command-line parameters:

     C:\>WMIRegistry.wsf /EaseKey:HKLM\Software\MyKeys /Action:Delete 

Sample 3.6: Deleting information in the registry (Part IV)

start example

 ...: ...: ...: 302: 303:    ' -- DELETE ------------------------------------------------------------------------- 304:    If boolDelete = True Then 305:       If Len (strKeyName) Then 306:          intRC = objWMIClass.DeleteValue (intHiveType, strBaseKey, strKeyName) 307:          If intRC Then 308:             WScript.Echo "Cannot delete registry key value '" & strKeyName & _ 309:                          "' under '" & strBaseKey & "' (" & intRC & ")." 310:          Else 311:             WScript.Echo "Registry key value '" & strKeyName & "' under '" & _ 312:                          strBaseKey & "' deleted." 313:          End If 314:       Else 315:          intRC = objWMIClass.DeleteKey(intHiveType, strBaseKey) 316:          If intRC Then 317:             WScript.Echo "Cannot delete registry key '" & strBaseKey & "' (" & intRC & ")." 318:          Else 319:             WScript.Echo "Registry key '" & strBaseKey & "' deleted." 320:          End If 321:       End If 322:    End If ...: 327: ...: ...: ...: 

end example

When a registry browse operation, search operation, or replace operation is requested, the BrowseRegistry() function is invoked (see Sample 3.7). This case corresponds to the following command-line parameters:

 C:\>WMIRegistry.wsf /BaseKey:HKLM\Software /Action:List /DisplayRegValues- C:\>WMIRegistry.wsf /BaseKey:HKLM\Software /Action:List /DisplayRegValues+ C:\>WMIRegistry.wsf /BaseKey:HKLM\SOFTWARE\MyKeys /Action:Search /SearchString:String C:\>WMIRegistry.wsf /BaseKey:HKLM\SOFTWARE\MyKeys /Action:Replace /SearchString:String                     /ReplaceString:MyString 

Sample 3.7: Browsing, searching, and replacing information in the registry (Part V)

start example

 ...: ...: ...: 327: 328:    ' ----------------------------------------------------------------------------------------- 329:    Function BrowseRegistry (objWMIClass, intHiveType, strBaseKey) ...: 338:        WScript.Echo strBaseKey 339:        If boolDisplayRegValues Then 340:           BrowseRegistryValues objWMIClass, intHiveType, strBaseKey 341:        End If 342: 343:        If Len (strBaseKey) Then 344:           strBackSlash = "\" 345:        Else 346:           strBackSlash = "" 347:        End If 348: 349:        intRC = objWMIClass.EnumKey (intHiveType, strBaseKey, strSubKeys) 350:        If intRC = 0 Then 351:           If IsNull (strSubKeys) = False Then 352:              If Ubound (strSubKeys) <> -1 Then 353:                 For intIndice = 0 To Ubound (strSubKeys) 354:                     BrowseRegistry objWMIClass, intHiveType, _ 355:                                    strBaseKey & strBackSlash & strSubKeys (intIndice) 356:                 Next 357:              End If 358:           End If 359:        End If 360: 361:    End Function 362: ...: ...: ...: 

end example

Displaying registry values occurs by default with a search or replace operation but not with a browse operation. To enable the values to be displayed during a browse, you must supply the /DisplayRegValue+ switch. The BrowseRegistryValues() function is invoked to browse the existing registry values (line 340). We will review the BrowseRegistryValues() function when discussing Sample 3.8.

Sample 3.8: Browsing, searching, and replacing information in the registry (Part VI)

start example

 ...: ...: ...: 362: 363:    ' ----------------------------------------------------------------------------------------- 364:    Function BrowseRegistryValues (objWMIClass, intHiveType, strKeyPath) ...: 383:        intRC = objWMIClass.EnumValues (intHiveType, strKeyPath, strKeyNames, intKeyTypes) 384:        If intRC = 0 Then 385:           If IsArray (strKeyNames) Then 386:              For intIndiceKeyName = 0 To Ubound (strKeyNames) 387:                  Select Case intKeyTypes (intIndiceKeyName) 388:                         Case REG_SZ 389:                              strKeyType = " (REG_SZ) " 390:                              intRC = objWMIClass.GetStringValue (intHiveType, strKeyPath, _ 391:                                                  strKeyNames (intIndiceKeyName), _ 392:                                                  varKeyValue) 393:                         Case REG_EXPAND_SZ 394:                              strKeyType = " (REG_EXPAND_SZ) " 395:                              intRC = objWMIClass.GetExpandedStringValue (intHiveType, _ 396:                                                  strKeyPath, _ 397:                                                  strKeyNames (intIndiceKeyName), _ 398:                                                  varKeyValue) 399:                         Case REG_MULTI_SZ 400:                              strKeyType = " (REG_MULTI_SZ) " 401:                              intRC = objWMIClass.GetMultiStringValue (intHiveType, strKeyPath, 402:                                                  strKeyNames (intIndiceKeyName), _ 403:                                                  varKeyValue) 404:                         Case REG_BINARY 405:                              strKeyType = " (REG_BINARY) " 406:                              intRC = objWMIClass.GetBinaryValue (intHiveType, strKeyPath, _ 407:                                                  strKeyNames (intIndiceKeyName), _ 408:                                                  varKeyValue) 409:                         Case REG_DWORD 410:                              strKeyType = " (REG_DWORD) " 411:                              intRC = objWMIClass.GetDWORDValue (intHiveType, strKeyPath, _ 412:                                                  strKeyNames (intIndiceKeyName), _ 413:                                                  varKeyValue) 414:                  End Select 415: 416:                  If intRC = 0 Then 417:                     boolDisplay = False 418:                     boolDisplayDeleted = False 419: 420:                     Select Case intBrowseLevel 421:                            Case cBrowse 422:                                 boolDisplay = True 423:                            Case csearch 424:                                 boolFoundInName = SearchString(strKeyNames(intIndiceKeyName), 425:                                                               strStringToSearch) 426:                                 boolFoundInValue = SearchString(varKeyValue, _ 427:                                                                 strStringToSearch) 428:                                 If boolFoundInValue Then 429:                                    intCounterValue = intCounterValue + 1 430:                                    boolDisplay = True 431:                                 End If 432:                                 If boolFoundInName Then 433:                                    intCounterValueName = intCounterValueName + 1 434:                                    boolDisplay = True 435:                                 End If 436:                            Case cReplace 437:                                 strOriginalKeyName = strKeyNames (intIndiceKeyName) 438: 439:                                 boolFoundInValue = ReplaceString (varKeyValue, _ 440:                                                                   strStringToSearch, _ 441:                                                                   strStringToReplace) 442:                                 boolFoundInName = ReplaceString(strKeyNames(intIndiceKeyName), 443:                                                                   strStringToSearch, _ 444:                                                                   strStringToReplace) 445:                                 If (boolFoundInName Or boolFoundInValue) Then 446:                                    intRC = SetRegistryValue (objWMIClass, intHiveType, _ 447:                                                              strKeyPath, _ 448:                                                              intKeyTypes(intIndiceKeyName), _ 449:                                                              strKeyNames(intIndiceKeyName), _ 450:                                                              varKeyValue) 451:                                    If intRC = 0 Then 452:                                       boolDisplay = True 453:                                    End If 454:                                    If boolFoundInValue Then 455:                                       intCounterValue = intCounterValue + 1 456:                                    End If 457:                                    If boolFoundInName Then 458:                                       intCounterValueName = intCounterValueName + 1 459:                                       intRC = objWMIClass.DeleteValue(intHiveType, _ 460:                                                                       strKeyPath, _ 461:                                                                       strOriginalKeyName) 462:                                       If intRC = 0 Then 463:                                          boolDisplayDeleted = True 464:                                       End If 465:                                    End If 466:                                 End If 467:                     End Select 468: 469:                     If Len (strKeyNames (intIndiceKeyName)) = 0 Then 470:                        strDisplayKeyName = "<DEFAULT>" 471:                     Else 472:                        strDisplayKeyName = strKeyNames (intIndiceKeyName) 473:                     End If 474: 475:                     If boolDisplay Then 476:                        Select Case intKeyTypes (intIndiceKeyName) 477:                               Case REG_MULTI_SZ 478:                                    WScript.Echo strKeyType & _ 479:                                                 strDisplayKeyName & _ 480:                                                 "=" & ConvertArrayInString (varKeyValue, _ 481:                                                                             ",", _ 482:                                                                             False) 483:                               Case REG_BINARY 484:                                    WScript.Echo strKeyType & _ 485:                                                 strDisplayKeyName & _ 486:                                                 "=" & ConvertArrayInString (varKeyValue, _ 487:                                                                             ",", _ 488:                                                                             True) 489:                               Case REG_DWORD 490:                                    WScript.Echo strKeyType & _ 491:                                                 strDisplayKeyName & _ 492:                                                 "=&h" & Hex(varKeyValue) 493:                               Case Else 494:                                    WScript.Echo strKeyType & _ 495:                                                 strDisplayKeyName & _ 496:                                                 "=" & varKeyValue 497:                        End Select 498: 499:                        If boolDisplayDeleted Then 500:                           WScript.Echo " Deleting" & strKeyType & _ 501:                                        strOriginalKeyName & _ 502:                                        " ... " 503:                        End If 504: 505:                     End If 506:                  End If 507:              Next 508:           End If 509:        End If 510: 511:    End Function 512: ...: ...: ...: 

end example

Sample 3.7 retrieves from the base key the list of subkeys available (line 349). The list is returned in an array, called strSubKeys, passed as a parameter of the EnumKey method of the StdRegProv class (line 349). If the array is properly initialized, the BrowseRegistry() function is recursively invoked and the new base key is passed by concatenating the current base key with each subkey found in the array (line 355).

If the registry values in a key are browsed, the BrowseRegistryValues() function is invoked (line 340). The BrowseRegistryValues() function code is shown in Sample 3.8.

This function can be divided into three parts:

  • The registry value reading (lines 383 through 414): This piece of code extracts the collection of values with the EnumValues method of the StdRegProv class (line 383). This method returns in two arrays the key value name (strKeyNames) and its corresponding type (intKey-Types). If the arrays are properly initialized, each array element is examined in a loop (lines 386 through 507) containing the two other portions of code (see the next two bullets). Based on the key value type (i.e., REG_SZ, REG_BINARY), the value is extracted from the registry with the StdRegProv method corresponding to the registry value type (lines 387 through 414).

  • The registry value parsing for a search or a replace operation (lines 416 through 467): Once the value is extracted, the desired browse operation is executed. If it is a simple browse operation to display the registry tree with its key values, the process forces a display of the value by setting a Boolean variable to True (line 422). For a search operation, the code invokes the SearchString() function for the examined key name (line 424) with its value (line 426). If a match is found, the matching value will be displayed later and a Boolean variable is set to True (lines 430 and 434). For a replace operation, first the code saves the original key name in a temporary variable (line 437). Next, the code invokes the ReplaceString() function for the examined key name (line 442) with its value (line 439). It is important to note that the ReplaceString() function automatically replaces the variable content of the key name ("strKeyNames (intIndiceKeyName)") with its value ("varKeyValue") if there is a match. If there is no match, no change to the original content of the variables is made. If a match is found, a new key is created with the updated content of the variables by invoking the SetRegistryValue() function. If the key name is modified by the replace operation, it means that the key with the original name still exists in the registry. This is why the script deletes the original key name by using the temporary variable initialized at line 437. The delete operation is executed at line 459.

  • The registry value display (lines 469 through 503): To display the key value with its name, the script checks if the key name is not blank. In such a case, it means that the key has no name and corresponds to a default registry value for the key (line 470). Next, the registry key value is converted according to its type (lines 476 through 497) for a suitable display.

Creating or updating a registry key value in the registry is pretty straightforward. The StdRegProv method corresponding to the registry key type (i.e., REG_SZ, REG_BINARY) must be invoked. This logic is shown in Sample 3.9 in lines 521 through 547.

Sample 3.9: Creating or updating information in the registry (Part VII)

start example

 ...: ...: ...: 512: 513:    ' ----------------------------------------------------------------------------------------- 514:    Function SetRegistryValue (objWMIClass, intHiveType, _ 515:                               strBaseKey, intKeyType, _ 516:                               strKeyName, varKeyNameValue) ...: 521:        Select Case intKeyType 522:               Case REG_SZ 523:                    intRC = objWMIClass.SetStringValue (intHiveType, _ 524:                                                        strBaseKey, _ 525:                                                        strKeyName, _ 526:                                                        varKeyNameValue) 527:               Case REG_MULTI_SZ 528:                    intRC = objWMIClass.SetMultiStringValue (intHiveType, _ 529:                                                             strBaseKey, _ 530:                                                             strKeyName, _ 531:                                                             varKeyNameValue) 532:               Case REG_EXPAND_SZ 533:                    intRC = objWMIClass.SetExpandedStringValue (intHiveType, _ 534:                                                                strBaseKey, _ 535:                                                                strKeyName, _ 536:                                                                varKeyNameValue) 537:               Case REG_BINARY 538:                    intRC = objWMIClass.SetBinaryValue (intHiveType, _ 539:                                                        strBaseKey, _ 540:                                                        strKeyName, _ 541:                                                        varKeyNameValue) 542:               Case REG_DWORD 543:                    intRC = objWMIClass.SetDWORDValue (intHiveType, _ 544:                                                       strBaseKey, _ 545:                                                       strKeyName, _ 546:                                                       varKeyNameValue) 547:        End Select 548: 549:        SetRegistryValue = intRC 550: 551:    End Function 552: 553:    ]]> 554:    </script> 555:  </job> 556:</package> 

end example

3.3.4 Session providers

The Session provider enables the management of network sessions and connections. The provider is implemented as an instance and method provider, as shown in Table 3.9.

Table 3.9: The Session Provider Capabilities

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

Session Provider

SessionProvider

Root/CIMV2

X

X

X

X

X

X

X

X

Available in the Root\CIMv2 namespace, the classes it supports are listed in Table 3.10.

Table 3.10: The Session Provider Classes

Name

Type

Comments

Win32_ServerConnection

Dynamic

Represents the connections made from a remote computer to a shared resource on the local computer.

Win32_ServerSession

Dynamic

Represents the sessions that have been established with the local computer, by users on a remote computer.

Win32_SessionConnection

Association

Represents an association between a session established with the local server, by a user on a remote machine, and the connections that depend on the session.

Win32_ConnectionShare

Association

Relates a shared resource on the computer and the connection made to the shared resource.

On one hand, the Win32_ServerConnection is associated with the Win32_Share class (with the help of the Win32_ConnectionShare association class), and on the other hand the Win32_ServerConnection is associated with the Win32_ServerSession class (with the help of the Win32_SessionConnection). These associations are shown in Figures 3.3 and 3.4, respectively.

click to expand
Figure 3.3: The Win32_Share and Win32_ServerConnection classes are associated with the Win32_ConnectionShare association class.

click to expand
Figure 3.4: The Win32_ServerSession and Win32_ServerConnection classes are associated with the Win32_SessionConnection association class.

The next sample demonstrates the code logic to retrieve the session information with its associated instances. This script sample doesn't expect any switch by default. So, if a machine with the IP address 192.10.10.3 has a connection established by the administrator on a share called "MyShare" and resides on the computer where the script is launched, the output would be as follows:

  1:   C:\>WMISessions.Wsf  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   - \\192.10.10.3\MYSHARE (ADMINISTRATOR) ------------------------------------------------  6:   ActiveTime: ............................. 443  7:   *ComputerName: .......................... 192.10.10.3  8:   ConnectionID: ........................... 174  9:   InstallDate: ............................ 01-01-2000 10:   NumberOfFiles: .......................... 0 11:   NumberOfUsers: .......................... 1 12:   *ShareName: ............................. MYSHARE 13:   *UserName: .............................. ADMINISTRATOR 14: 15:    -- Session connection information ---------------------------------------------------- 16:    ActiveTime: ........................... 443 17:    ClientType: ........................... Windows .NET 3718 18:    *ComputerName: ........................ 192.10.10.3 19:    IdleTime: ............................. 8 20:    InstallDate: .......................... 01-01-2000 21:    Resourcesopened:. ...................... 0 22:    SessionType:. .......................... 2 23:    TransportName: ........................ \Device\NetbiosSmb 24:    *UserName: ............................ ADMINISTRATOR 25: 26:    -- Share connection information ------------------------------------------------------ 27:    AllowMaximum: ......................... TRUE 28:    Caption: .............................. MYSHARE 29:    Description: .......................... 30:    InstallDate: .......................... 01-01-2000 31:    *Name: ................................ MYSHARE 32:    Path: ................................. J:\MYDIR 33:    Status: ............................... OK 34:    Type: ................................. Disk 

First, the script retrieves the Win32_ServerConnection instances (lines 5 through 13); next, it retrieves the Win32_ServerSession associated instances (lines 15 through 24) with some basic information about the Win32_Share associated instance (lines 26 and 27).

It is also possible to delete a session based on the computer name. The command line will be as follows:

 C:\>WMISessions.Wsf /Delete:192.10.10.3 Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Session '192.10.10.3' deleted. Completed. 

The code is shown in Sample 3.10. Since the command-line parameters definition and parsing are pretty simple and use the same logic as previous samples, they have been skipped. Right after the WMI connection (lines 69 through 73), the script checks if a computer name is specified with the /Delete switch. If not, it processes the display of the session information (lines 78 through 150). If a computer name is specified, it processes the deletion of the sessions established from the given computer name (lines 153 through 167).

Sample 3.10: Viewing the active sessions with their associations

start example

   l:<?xml version="1.0"?>   .:   8:<package>   9:  <job>   .:  13:    <runtime>  ..:  24:    </runtime>  25:  26:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodeShareTypeFunction.vbs" />  27:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" />  28:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  29:  30:    <object prog  reference="true"/>  31:    <object prog  />  32:  33:    <script language="VBscript">  34:    <![CDATA[  ..:  38:    Const cComputerName = "LocalHost"  39:    Const cWMINameSpace = "Root/cimv2"  40:    Const cWMIConnClass = "Win32_ServerConnection"  41:    Const cWMISessionClass = "Win32_ServerSession"  ..:  56:    ' --------------------------------------------------------------------------------  ..:  69:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault  70:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate  71:  72:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _  73:                                                     strUserID, strPassword)  ..:  76:    If Len(strComputer) = 0 Then  77:       ' -- LIST ---------------------------------------------------------------------------  78:       Set objWMIInstances = objWMIServices.InstancesOf (cWMIConnClass)  ..:  81:       If objWMIInstances.Count Then  82:          For Each objWMIInstance In objWMIInstances  83:              WScript.Echo "- \\" & Ucase (objWMIInstance.ComputerName) & _  84:                           "\" & Ucase (objWMIInstance.ShareName) & _  85:                           " (" & Ucase (objWMIInstance.UserName) & _  86:                           ") " & String (60, "-")  87:              Set objWMIPropertySet = objWMIInstance.Properties_  88:              For Each objWMIProperty In objWMIPropertySet  89:                  DisplayFormattedProperty objWMIInstance, _  90:                         objWMIProperty.Name, _  91:                         objWMIProperty.Name, _  92:                         Null  93:              Next  ..:  96:              Set objWMIAssocInstances = objWMIServices.ExecQuery _  97:                                  ("Associators of {" & objWMIInstance.Path_.RelPath & _  98:                                  "} Where AssocClass=Win32_SessionConnection") ...: 101:              If objWMIAssocInstances.Count Then 102:                 WScript.Echo 103:                 WScript.Echo " -- Session connection information " & " " & String (53, "-") 104:                 For Each objWMIAssocInstance In objWMIAssocInstances 105:                     Set objWMIPropertySet = objWMIAssocInstance.Properties_ 106:                     For Each objWMIProperty In objWMIPropertySet 107:                         DisplayFormattedProperty objWMIAssocInstance, _ 108:                                " " & objWMIProperty.Name, _ 109:                                objWMIProperty.Name, _ 110:                                Null 111:                 Next 112:                 Set objWMIPropertySet = Nothing 113:                 Next 114:              End If 115: 116:              Set objWMIAssocInstances = objWMIServices.ExecQuery _ 117:                                  ("Associators of {" & objWMIInstance.Path_.RelPath & _ 118:                                  "} Where AssocClass=Win32_ConnectionShare") ...: 121:              If objWMIAssocInstances.Count Then 122:                 WScript.Echo 123:                 WScript.Echo " -- Share connection information " & " " & String (53, "-") 124:                 For Each objWMIAssocInstance In objWMIAssocInstances 125:                     Set objWMIPropertySet = objWMIAssocInstance.Properties_ 126:                     For Each objWMIProperty In objWMIPropertySet 127:                         Select Case objWMIProperty.Name 128:                                Case "Type" 129:                                     DisplayFormattedProperty objWMIAssocInstance, _ 130:                                            " " & objWMIProperty.Name, _ 131:                                            ShareType (objWMIProperty.Value), _ 132:                                            Null 133: 134:                                Case Else 135:                                     DisplayFormattedProperty objWMIAssocInstance, _ 136:                                            " " & objWMIProperty.Name, _ 137:                                            objWMIProperty.Name, _ 138:                                            Null 139:                         End Select 140:                     Next 141:                     Set objWMIPropertySet = Nothing 142:                 Next 143:              End If 144:              WScript.Echo ...: 147:          Next 148:       Else 149:          WScript.Echo "No session." & vbCRLF 150:       End If 151:    Else 152:       ' -- Delete --------------------------------------------------------------------------- 153:       Set objWMIInstances = objWMIServices.ExecQuery ("Select * From " & cWMISessionClass & _ 154:                                            " Where ComputerName='" & strComputer & "'") ...: 157:       If objWMIInstances.Count Then 158:          For Each objWMIInstance In objWMIInstances 159:              objWMIInstance.Delete_ ...: 162:              WScript.Echo "Session '" & objWMIInstance.ComputerName & "' deleted." 163:          Next 164:          WScript.Echo 165:       End If ...: 168:    End If 169: 170:    WScript.Echo "Completed." ...: 176:    ]]> 177:    </script> 178:  </job> 179:</package> 

end example

When the script displays session information, it retrieves a collection of Win32_ServerConnection instances (line 78). For each instance (lines 82 through 147), the script displays the instance properties (lines 87 through 93) with the existing associated instances. As we have seen in Figures 3.3 and 3.4, two associated instances with their properties can be retrieved:

  • The Win32_ServerSession instances associated with the Win32_Ses-sionConnection association class (lines 96 through 114)

  • The Win32_Share instances associated with the Win32_Connection-Share association class (lines 116 through 143).

    Once completed, the script terminates its execution.

With the /Delete switch, sessions established by a specific computer can be deleted (lines 153 through 167). Instead of retrieving a specific session, based on the command-line parameters, the script retrieves all sessions available for the given computer (lines 153 and 154) and deletes them (line 159) in a loop (lines 158 through 163).

3.3.5 Kernel Job providers

Installed on Windows XP and Windows Server 2003, the Kernel Job Object provider enables access to data on named kernel job objects. This provider does not report unnamed kernel job objects. The Kernel Job Object providers capabilities are listed in Table 3.11.

Table 3.11: The Kernel Job Object Providers Capabilities

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

Job Object Providers

NamedJobObjectActgInfoProv

Root/CIMV2

X

X

X

X

X

X

X

NamedJobObjectLimitSettingProv

Root/CIMV2

X

X

X

X

X

X

X

NamedJobObjectProv

Root/CIMV2

X

X

X

X

X

X

X

NamedJobObjedSecLimitSettingProv

Root/CIMV2

X

X

X

X

X

X

X

The classes supported by these providers are available in the Root\CIMv2 namespace and summarized in Table 3.12.

Table 3.12: The Kernel Job Object Classes

Name

Type

Comments

Win32_NamedJobObject

Dynamic

Represents a kernel object that is used to group processes for the sake of controlling the life and resources of the processes within the job object.

Win32_NamedJobObjectActglnfo

Dynamic

Represents the I/O accounting information for a job object.

Win32_NamedJobObjectLimitSetting

Dynamic

Represents the limit settings for a job object.

Win32_NamedJobObjectSecLimitSetting

Dynamic

Represents the security limit settings for a job object.

Win32_SIDandAttributes

Dynamic

Represents a security identifier (SID) and its attributes.

Win32_NamedJobObjectProcess

Association

Aggregation

Relates a job object and the process contained in the job object.

Win32_CollectionStatistics

Association

Relates a managed system element collection and the class representing statistical information about the collection.

Win32_NamedJobObjectLimit

Association

Represents an association between a job object and the job object limit settings.

Win32_NamedJobObjectSecLimit

Association

Relates a job object and the job object security limit settings.

Win32_NamedJobObjectStatistics

Assocation

Represents an association between a job object and the job object I/O accounting information class.

Win32_LUID

Abstract

Represents a locally unique identifier (LUID)

Win32_LUlDandAttributes

Abstract

Represents a LUID and its attributes.

Win32_TokenGroups

Abstract

Represents information about the group SIDs in an access token.

Win32_TokenPrivileges

Abstract

Represents information about a set of privileges for an access token.

The Win32_NamedJobObject class represents a kernel object that is used to group processes for the sake of controlling the life and resources of the processes within the job object. Figure 3.5 shows the associations in place.

click to expand
Figure 3.5: The Win32_NamedJobObjectassociations.

As we can see in Figure 3.5, the Win32_NamedJobObject\\iiS an association with the Win32_Process. In the previous chapter, we developed a script using the Win32_Process (see Sample 2.50, "Viewing, creating, and killing processes"). We can easily extend this previous sample to show the information available from the associations shown in Figure 3.5. We won't review the complete script. Only the portion of the code showing the process information will be examined. Until line 333, the script is exactly the same as Sample 2.50. The portion of code is included from line 335 through 389 and is executed for each Win32_Process instance examined during the loop (lines 289 through 386).

Sample 3.11: Viewing Job kernel instance associated with a process

start example

 ...: ...: ...: 275:    ' - LIST ---------------------------------------------------------------------------------- 276:    If boolList Then 277:       If Len (strExecutable) Then 278:          Set objWMIProcInstances = objWMIServices.ExecQuery ("Select * From " & _ 279:                                                              cWMIProcClass & _ 280:                                                              " Where Name='" & _ 281:                                                              strExecutable & "'") 282:          If Err.Number Then ErrorHandler (Err) 283:       Else 284:          Set objWMIProcInstances = objWMIServices.InstancesOf (cWMIProcClass) 285:          If Err.Number Then ErrorHandler (Err) 286:       End If 287: 288:       If objWMIProcInstances.Count Then 289:          For Each objWMIProcInstance in objWMIProdnstances 290:              WScript.Echo "- " & Ucase (objWMIProcInstance .Name) & String (60, "-") 291:              Set objWMIPropertySet = objWMIProcInstance. Properties_ 292:              For Each objWMIProperty In objWMIPropertySet 293:                  Select Case objWMIProperty.Name 294:                         Case "Caption" 295: 296:                         Case "Description" 297: 298:                         Case "Name" 299: 300:                         Case "CSCreationClassName" 301: 302:                         Case "OSCreationClassName" 303: 304:                         Case "CreationClassName" 305: 306:                         Case Else 307:                              DisplayFormattedProperty objWMIProcInstance, _ 308:                                                       "  " & objWMIProperty.Name, _ 309:                                                       objWMIProperty.Name, _ 310:                                                       Null 311:                  End Select 312:              Next 313:              Set objWMIPropertySet = Nothing 314: 315:              WScript.Echo 316: 317:              intRC = objWMIProdnstance. GetOwner (strOwnerUser, strOwnerDomain) 318:              If intRC = 0 Then 319:                 DisplayFormattedProperty objWMIProcInstance, _ 320:                                          "  Process owner", _ 321:                                          strOwnerDomain, _ 322:                                          strOwnerUser 323:              End If 324: 325:              intRC = objWMIProdnstance. GetOwnerSid (strOwnerSID) 326:              If intRC = 0 Then 327:                 DisplayFormattedProperty objWMIProcInstance, _ 328:                                          "  Process owner SID", _ 329:                                          strOwnerSID, _ 330:                                          Null 331:              End If 332: 333:              WScript.Echo 334: 335:              Set objWMIJobInstances = objWMIServices.ExecQuery _ 336:                                            ("Associators of {" & _ 337:                                            objWMIProcInstance. Path_.RelPath & _ 338:                                            "} Where AssocWin32_NamedJobObjectProcess") 340: 341:              If objWMIJobInstances.Count Then 342:                 For Each objWMIJobInstance in objWMIJobInstances 343:                     WScript.Echo "  - " & Ucase(objWMIJobInstance.CollectionID) & _ 344:                                  " " & String (60, "-") 345:                     Set objWMIPropertySet = objWMIJobInstance.Properties_ 346:                     For Each objWMIProperty In objWMIPropertySet 347:                         DisplayFormattedProperty objWMIJobInstance, _ 348:                                                  "    " & objWMIProperty.Name, _ 349:                                                  objWMIProperty.Name, _ 350:                                                  Null 351:                     Next 352:                     Set objWMIPropertySet = Nothing 353: 354:                     WScript. Echo 355: 356:                     For Each strAssocClass In Array ("Win32_NamedJobObjectLimit", _ 357:                                                      "Win32_NamedJobObjectSecLimit", _ 358:                                                      "Win32_NamedJobObjectStatistics") 359: 360:                         Set objWMIJobAssocInstances = objWMIServices.ExecQuery _ 361:                                                        ("Associators of {" & _ 362:                                                        objWMIJobInstance.Path_.RelPath & _ 363:                                                        "} Where Assoc    - " & _ 369:                                             Ucase (objWMIJobAssocInstance. Path_.Class) & _ 370:                                             " " & String (60, "-") 371:                                Set objWMIPropertySet = objWMIJobAssocInstance . Properties_ 372:                                For Each objWMIProperty In objWMIPropertySet 373:                                    DisplayFormattedProperty objWMIJobAssocInstance, _ 374:                                                             "     " & objWMIProperty.Name, _ 375:                                                              objWMIProperty.Name, _ 376:                                                              Null 377:                                Next 378:                                Set objWMIPropertySet = Nothing 379: 380:                                WScript.Echo 381:                            Next 382:                         End If 383:                     Next 384:                 Next 385:              End If 386:          Next 387:       Else 388:          WScript.Echo "No information available." 389:       End If ...: ...: ...: 

end example

At line 335, the script retrieves the Win32_NamedJobObject instances associated with the Win32_NamedObjectProcess association class. If instances of the Win32_NamedJobObject class are available (line 341), the script displays their properties (lines 345 through 352). Next, for each instance of the Win32_NamedJobObject class, the script retrieves three associated instances (lines 356 through 383):

  • The Win32_NamedJobObjectLimitSetting instances with the Win32_NamedJobObjectLimit association class.

  • The Win32_NamedJobObjectActgInfo instances with the Win32_NamedJobObjectActgInfo association class.

  • The Win32_NamedJobObjectSecLimitSetting instances with the Win32_NamedJobObjectSecLimitSetting association class.

The obtained output for the WMI process is as follows:

  1:  C:\>WMIProcess /Action:List /Executable:wmiprvse.exe  2:  Microsoft (R) Windows Script Host Version 5.6  3:  Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:  - WMIPRVSE.EXE- ---------------------------------------------------------------------  6:    CreationDate: ......................... 09-02-2002 07:18:37   7:    CSName: ............................... NET-DPEN6400A  8:    *Handle: .............................. 2712  9:    HandleCount: .......................... 175 10:    InstallDate: .......................... 09-02-2002 07:18:37 11:    KernelModeTime: ....................... 24234848 12:    OSName: ............................... Microsoft Windows .NET Enterprise Serv... 13:    OtherOperationCount: .................. 4967 14:    OtherTransferCount: ................... 44708 15:    PageFaults: ........................... 10974 16:    PageFileUsage: ........................ 3674112 17:    ParentProcessId: ...................... 696 18:    PeakPageFileUsage: .................... 3977216 19:    PeakVirtualSize: ...................... 29556736 20:    PeakWorkingSetSize: ................... 7913472 21:    Priority: ............................. 8 22:    PrivatePageCount: ..................... 3674112 23:    ProcessId: ............................ 2712 24:    QuotaNonPagedPoolUsage: ............... 5656 25:    QuotaPagedPoolUsage: .................. 25264 26:    QuotaPeakNonPagedPoolUsage: ........... 7744 27:    QuotaPeakPagedPoolUsage: .............. 26268 28:    ReadOperationCount: ................... 2846 29:    ReadTransferCount: .................... 938974 30:    SessionId: ............................ 0 31:    TerminationDate: ...................... 09-02-2002 07:18:37 32:    ThreadCount: .......................... 9 33:    UserModeTime: ......................... 60887552 34:    VirtualSize: .......................... 27336704 35:    WindowsVersion: ....................... 5.1.3590 36:    WorkingSetSize: ....................... 7864320 37:    WriteOperationCount: .................. 2383 38:    WriteTransferCount: ................... 144244 39: 40:    Process owner: ........................ NT AUTHORITY NETWORK SERVICE 41:    Process owner SID: .................... S-1-5-20 42: 43:    - \WMI\PROVIDER\SUB\SYSTEM\HOST\JOB ------------------------------------- 44:      BasicUIRestrictions: ................ 0 45:      *CollectionID: ...................... \wmi\provider\sub\system\host\job 46: 47:      - WIN32_NAMEDJOBOBJECTLIMITSETTING ----------------------------------------------------------- 48:        ActiveProcessLimit: ............... 32 49:        Affinity: ......................... 0 50:        JobMemoryLimit: ................... 1073741824 51:        LimitFlags: ....................... 11016 52:        MaximumWorkingSetSize: ............ 0 53:        MinimumWorkingSetSize: ............ 0 54:        PerJobUserTimeLimit: .............. 0 55:        PerProcessUserTimeLimit: .......... 0 56:        PriorityClass: .................... 32 57:        ProcessMemoryLimit: ............... 134217728 58:        SchedulingClass: .................. 5 59:        *SettingID: ....................... \wmi\provider\sub\system\host\job 60: 61:      - WIN32_NAMEDJOBOBJECTSECLIMITSETTING ------------------------------------------------------- 62:        PrivilegesToDelete: ............... <OBJECT> 63:        RestrickedSIDs: ................... <OBJECT> 64:        SecurityLimitFlags: ............... 0 65:        *SettingID: ....................... \wmi\provider\sub\syskem\host\iob 66:         SIDsToDisable: .................... <OBJECT> 67: 68:      - WIN32_NAMEDJOBOBJECTACTGINFO --------------------------------- 69:        ActiveProcesses: .................. 1 70:        *Name: ............................ \wmi\provider\sub\system\host\job 71:        OtherOperationCount: .............. 4975 72:        OtherTransferCount: ............... 44708 73:        PeakJobMemoryUsed: ................ 3977216 74:        PeakProcessMemoryUsed: ............ 4136960 75:        ReadOperationCount: ............... 2885 76:        ReadTransferCount: ................ 941298 77:        ThisPeriodTotalKernelTime: ........ 24935856 78:        ThisPeriodTotalUserTime: .......... 62790288 79:        TotalKernelTime: .................. 24935856 80:        TotalPageFaultCount: .............. 11105 81:        TotalProcesses: ................... 1 82:        TotalTerminatedProcesses: ......... 0 83:        TotalUserTime: .................... 62790288 84:        WriteOperationCount: .............. 2422 85:        WriteTransferCount: ............... 146912 

3.3.6 TrustMon provider

Only available under Windows Server 2003, the TrustMon provider is an instance provider that only supports the "Get" and "Enumeration" operations (Table 3.13).

Table 3.13: The TrustMon Provider Capabilities

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

Trust Monitoring Providers

TrustPrv

Root/ActiveDirectory

X

X

X

X

Supporting three classes available in the Root\MicrosoftActiveDirectory namespace (Table 3.14), the provider purpose is to verify the state of the existing trust relationships between domains.

Table 3.14: The TrustMon Provider Classes

Name

Type

Comments

Microsoft_TrustProvider

Dynamic (Singleton)

Provider parameterization class.

Microsoft_DomainTrustStatus

Dynamic

Trust enumerator class.

Microsoft_LocalDomainlnfo

Dynamic (Singleton)

Local domain information class.

The Microsoft_TrustProvider class is a singleton class and includes properties that control how domains will be enumerated with the Microsoft_DomainTrustStatus class. The TrustMon provider caches the last trust enumeration (default ListLifeTime = 20 min) and the last request for the trust status (default StatusLifeTime = 3 min). It is also possible to define the trust check level (Table 3.15), if only the trusting domains must be returned (without the trusted domains).

Table 3.15: The TrustMon Check Levels

Meaning

Values

Enumerate only

0

Enumerate with SC_QUERY

1

Enumerate with password check

2

Enumerate with SC_RESET

3

The Microsoft_LocalDomainInfo class is used to gather information about the domain, while the last class, the Microsoft_DomainTrustStatus class, is used to enumerate the trust status. The verification of the trusts is made during the enumeration of the Microsoft_DomainTrustStatus class based on the parameters given at the level of the Microsoft_TrustProvider instance. It is important to note that the effectiveness of the updated parameters is not immediate, even if the Microsoft_TrustProvider instance is updated immediately before the trust enumeration. The only way to immediately change the provider parameters is to update the settings stored in the repository and stopping/restarting the WMI service WinMgmt.Exe. Based on this information, Sample 3.12 has the following command-line parameters:

 C:\>WMITrust.Wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMITrust.wsf /Check:value [/ListLifeTime:value] [/StatusLifeTime:value] [/TrustingOnly[+|-]]                                  [/DomainInfo[+|-]] [/Machine:value] [/User:value] [/Password:value] Options: Check          :Specify the verification to perform: [EnumOnly], [EnumQuery], [EnumPwdCheck] or [EnumReset]. ListLifeTime   :Time in minutes to cache the last trust enumeration. StatusLifeTime :Time in minutes to cache the last request for status. TrustingOnly   :If TRUE, enumerations return trusting as well as trusted domains. DomainInfo     :Provide information about the domain on which this instance of the trust monitor is running. Machine        :Determine the WMI system to connect to. (default=LocalHost) User           :Determine the UserID to perform the remote connection. (default=none) Password       :Determine the password to perform the remote connection. (default=none) Examples:       WMITrust /DomainInfo+       WMITrust /Check:EnumOnly /StatusLifeTime:3 /ListLifeTime:20 /TrustingOnly+       WMITrust /Check:EnumQuery /ListLifeTime :20 /TrustingOnly+       WMITrust /Check:EnumPwdCheck /StatusLifeTime:3 /TrustingOnly+       WMITrust /Check:EnumReset /TrustingOnly+ 

Sample 3.12: Verifying trusts

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  31:    </runtime>  32:  33:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodeTrustsFunction.vbs" />  34:  35:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" />  36:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  37:  38:    <object prog  reference="true"/>  39:    <object prog  />  40:  41:    <script language="VBscript">  42:    <![CDATA[  ..:  46:    Const cComputerName = "LocalHost"  47:    Const cWMINameSpace = "Root\MicrosoftActiveDirectory"  48:    Const cWMITrustProvClass = "Microsoft_TrustProvider"  49:    Const cWMIDomTrustClass = "Microsoft_DomainTrustStatus"  50:    Const cWMIDomlnfoClass = "Microsoft_LocalDomainInfo'  ..:  72:    ' -----------------------------------------------------------------------------------------------  73:    ' Parse the command line parameters  74:    If WScript.Arguments.Named.Count = 0 Then  75:       WScript.Arguments.ShowUsage()  76:       WScript.Quit  77:    End If  ..: 122:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 123: 124:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 125:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 126: 127:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 128:                                                     strUserID, strPassword) ...: 131:    If boolDomainInfo = True Then 132:       ' ------------------------------------------------------------------------------------------------------ 133:       WScript.Echo "- Local Domain information " & String (60, "-") 134: 135:       Set objWMIInstance = objWMIServices.Get (cWMIDomInfoClass & "=@") 136:       If Err.Number Then ErrorHandler (Err) 137: 138:       Set objWMIPropertySet = objWMIInstance.Properties_ 139:       For Each objWMIProperty In objWMIPropertySet 140:           DisplayFormattedProperty objWMIInstance, _ 141:                                    "  " & objWMIProperty.Name, _ 142:                                    objWMIProperty.Name, _ 143:                                    Null 144:       Next 145: 146:       WScript.Echo 147:       WScript.Echo "- Trust provider parameters " & String (60, "-") 148: 149:       Set objWMIInstance = objWMIServices .Get (cWMITrustProvClass & "=@") ...: 152:       Set objWMIPropertySet = objWMIInstance.Properties_ 153:       For Each objWMIProperty In objWMIPropertySet 154:           DisplayFormattedProperty objWMIInstance, _ 155:                                    "  " & objWMIProperty.Name, _ 156:                                    objWMIProperty.Name, _ 157:                                    Null 158:       Next ...: 162:    Else 163:       ' --------------------------------------------------------------------------------------------------------- 164:       Set objWMIInstance = objWMIServices .Get (cWMITrustProvClass & "=@") ...: 167:       objWMIInstance.TrustCheckLevel = intCheckLevel 168: 169:       If intStatusLifeTime <> - 1 Then 170:          objWMIInstance.TrustStatusLifetime = intStatusLifeTime 171:       End If 172:       If intListLifeTime <> - 1 Then 173:          objWMIInstance.TrustListLifetime = intListLifeTime 174:       End If 175:       If Len(boolTrustingOnly) Then 176:          objWMIInstance.ReturnAll = Not boolTrustingOnly 177:       End If 178: 179:       objWMIInstance.Put_ (wbemChangeFlagUpdateOnly Or wbemFlagReturnWhenComplete) ...: 184:       ' --------------------------------------------------------------------------------------------------------- 185:       Set objWMIInstances = objWMIServices.InstancesOf (cWMIDomTrustClass) ...: 188:       For Each objWMIInstance in objWMIInstances 189:           Set objWMIPropertySet = objWMIInstance.Properties_ 190:           For Each objWMIProperty In objWMIPropertySet 191:               Select Case objWMIProperty.Name 192:                      Case "TrustDirection" 193:                           DisplayFormattedProperty objWMIInstance, _ 194:                                  "  " & objWMIProperty.Name, _ 195:                                  DecodeTrustDirection (objWMIProperty.Value), _ 196:                                  Null 197:                      Case "TrustType" 198:                           DisplayFormattedProperty objWMIInstance, _ 199:                                  "  " & objWMIProperty.Name, _ 200:                                  DecodeTrustType (objWMIProperty.Value), _ 201:                                  Null 202:                      Case "TrustAttributes" 203:                           DisplayFormattedProperty objWMIInstance, _ 204:                                  "  " & objWMIProperty.Name, _ 205:                                  DecodeTrustAttributes (objWMIProperty.Value), _ 206:                                  Null 207:                      Case Else 208:                           DisplayFormattedProperty objWMIInstance, _ 209:                                  "  " & objWMIProperty.Name, _ 210:                                  objWMIProperty.Value, _ 211:                                  Null 212:               End Select 213;            Next ...: 216:       Next ...: 219:    End If ...: 223:    ]]> 224:    </script> 225:  </job> 226: </package> 

end example

Requesting the domain information will also show the TrustMon provider parameters. For example, the following command line would give:

 C:\>WMITrust /DomainInfo+ Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. - Local Domain information ------------------------------------------------------------   DCname: ................................. NET-DPEN6400A   DNSname: ................................ LissWare.NET   FlatName: ............................... LISSWARENET   SID: .................................... S-l-5-21-1935655697-839522115-1708537768   TreeName: ............................... LissWare.Net - Trust provider parameters ------------------------------------------------------------   ReturnAll: .............................. TRUE   TrustCheckLevel: ........................ 2   TrustListLifetime: ...................... 0   TrustStatusLifetime : .................... 0 

While the following command line would give:

 C:\>WMITrust /Check:EnumPwdCheck /TrustingOnly- Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.   FlatName: .............................. EMEA   SID: ................................... S-l-5-21-1708537768-854245398-1957994488   TrustAttributes: ....................... 0   TrustDirection: ........................ Bi-directional   TrustedDCName: .........................    TrustedDomain: ......................... Emea.LissWare.Net   TrustIsOk: ............................. False   TrustStatus: ........................... 1355   TrustStatusString: ..................... The specified domain either does not exist                                            or could not be contacted.   TrustType: ............................. Uplevel   FlatName: .............................. MYNT40DOMAIN   SID: ................................... S-l-5-21-42165204-196285673-1159422225   TrustAttributes: ....................... 0   TrustDirection: ........................ Inbound   TrustedDCName: .........................    TrustedDomain: ......................... HOME   TrustlsOk: ............................. True   TrustStatus: ........................... 0   TrustStatusString: ..................... Inbound-only trusts are verified from the   trusting side.   TrustType: ............................. Downlevel 

Sample 3.12 shows the code logic developed on top of the TrustMon provider. The command-line parameter definitions and parsing follow the same structure as previous script samples.

When the /DomainInfo+ switch is supplied on the command line, the script gets the Microsoft_LocalDomainInfo (lines 135 through 144) and Microsoft_TrustProvider instances (lines 149 through 158) to display their properties. If the /DomainInfo switch is not supplied, the script updates the Microsoft_TrustProvider instance with the command-line parameters (lines 164 through 179) and enumerates the list of trusts in place (lines 185 through 216).

To detect a trust status change, a WQL event query can be used. Since the TrustMon provider is not implemented as an event provider, the WQL event query must use the WITHIN statement. For example, a valid WQL would be as follows:

  1:    C:\>GenericEventAsyncConsumer.wsf "Select * FROM __InstanceModificationEvent Within 5                                          Where TargetInstance ISA 'Microsoft_DomainTrustStatus'"                                          /NameSpace:Root\MicrosoftActiveDirectory  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   Waiting for events...  6:  7:   BEGIN - OnObjectReady.  8:   Monday, 10 June, 2002 at 12:11:12: '__InstanceModificationEvent' has been triggered.  9:     PreviousInstance (wbemCimtypeObject) 10:       FlatName (wbemCimtypeString) = EMEA 11:       SID (wbemCimtypeString) = S-1-5-21-1060284298-484763869-1343024091 12:       TrustAttributes (wbemCimtypeUint32) = 0 13:       TrustDirection (wbemCimtypeUint32) = 3 14:       TrustedDCName (wbemCimtypeString) = \\net-dpep6400a.Emea.LissWare.NET 15:       *TrustedDomain (wbemCimtypeString) = Emea.LissWare.NET 16:       TrustIsOk (wbemCimtypeBoolean) = True 17:       TrustStatus (wbemCimtypeUint32) = 0 18:       TrustStatusString (wbemCimtypeString) = The secure channel was reset and the trust is OK. 19:       TrustType (wbemCimtypeUint32) = 2 20:     SECURITY_DESCRIPTOR (wbemCimtypeUint8) = (null) 21:     TargetInstance (wbemCimtypeObject) 22:       FlatName (wbemCimtypeString) = EMEA 23:       SID (wbemCimtypeString) = S-1-5-21-1060284298-484763869-1343024091 24:       TrustAttributes (wbemCimtypeUint32) = 0 25:       TrustDirection (wbemCimtypeUint32) = 3 26:       TrustedDCName (wbemCimtypeString) = \\net-dpep6400a.Emea.LissWare.NET 27:       *TrustedDomain (wbemCimtypeString) = Emea.LissWare.NET 28:       TrustIsOk (wbemCimtypeBoolean) = False 29:       TrustStatus (wbemCimtypeUint32) = 1311 30:       TrustStatusString (wbemCimtypeString) = There are currently no logon servers                                                   available to service the logon request. 31:       TrustType (wbemCimtypeUint32) = 2 32:     TIME_CREATED (wbemCimtypeUint64) = (null) 33: 34:   END - OnObjectReady. 35: 36:   BEGIN - OnObjectReady. 37:   Monday, 10 June, 2002 at 12:11:12: '__InstanceModificationEvent' has been triggered. 38:     PreviousInstance (wbemCimtypeObject) 39:       FlatName (wbemCimtypeString) = EMEA 40:       SID (wbemCimtypeString) = S-1-5-21-1060284298-484763869-1343024091 41:       TrustAttributes (wbemCimtypeUint32) = 0 42:       TrustDirection (wbemCimtypeUint32) = 3 43:       TrustedDCName (wbemCimtypeString) = \\net-dpep6400a.Emea.LissWare.NET 44:       *TrustedDomain (wbemCimtypeString) = Emea.LissWare.NET 45:       TrustIsOk (wbemCimtypeBoolean) = False 46:       TrustStatus (wbemCimtypeUint32) = 1311 47:       TrustStatusString (wbemCimtypeString) = There are currently no logon servers                                                   available to service the logon request. 48:       TrustType (wbemCimtypeUint32) = 2 49:     SECURITY_DESCRIPTOR (wbemCimtypeUint8) = (null) 50:     TargetInstance (wbemCimtypeObject) 51:       FlatName (wbemCimtypeString) = EMEA 52:       SID (wbemCimtypeString) = S-1-5-21-1060284298-484763869-1343024091 53:       TrustAttributes (wbemCimtypeUint32) = 0 54:       TrustDirection (wbemCimtypeUint32) = 3 55:       TrustedDCName (wbemCimtypeString) = \\net-dpep6400a.Emea.LissWare.NET 56:       *TrustedDomain (wbemCimtypeString) = Emea.LissWare.NET 57:       TrustIsOk (wbemCimtypeBoolean) = False 58:       TrustStatus (wbemCimtypeUint32) = 1355 59:       TrustStatusString (wbemCimtypeString) = The specified domain either does not exist                                                   or could not be contacted. 60:       TrustType (wbemCimtypeUint32) = 2 61:     TIME_CREATED (wbemCimtypeUint64) = (null) 62: 63:   END - OnObjectReady. 

From line 7 through 34, the trust status changes from 0 to 1311 (line 17 versus line 29), generating an error message at line 30. From line 36 through 63, the trust status changes from 1311 to 1355 (line 46 versus line 58), generating a different error message at line 59.

3.3.7 Windows Proxy provider

The Windows Proxy provider supports one single class called Win32_Proxy and is located in the Root\CIMv2 namespace. This provider is implemented as an instance and a method provider (Table 3.16) and manages the Windows Proxy LAN settings.

Table 3.16: The Windows Proxy Providers Capabilities

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

Proxy Provider

Win32_WIN32_PROXY_Prov

Root/CIMv2

X

X

X

X

X

X

X

X

The information exposed by the Win32_Proxy class is similar to the information exposed by the MicrosoftIE_LanSettings class in Root/CIMV2/Applications/MicrosoftIE namespace. However, the MicrosoftIE_LanSettings class uses the IEINFO5 provider. With the SetProxySetting method exposed by the Win32_Proxy class, it is possible to update the Proxy LAN settings. Sample 3.13 shows how to proceed.

Sample 3.13: Managing the Windows Proxy LAN settings

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  26:    </runtime>  27:  28:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" />  29:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  30:  31:    <object prog  reference="true"/>  32:    <object prog  />  33:  34:    <script language="VBscript">  35:    <![CDATA[  ..:  39:    Const cComputerName = "LocalHost"  40:    Const cWMINameSpace = "Root\CIMv2"  41:    Const cWMIClass = "Win32_Proxy"  ..:  62:    ' --------------------------------------------------------------------------------  63:    ' Parse the command line parameters  64:    If WScript.Arguments.Named.Count = 0 Then  65:       WScript.Arguments.ShowUsage()  66:       WScript.Quit  67:    End If  ..:  99:    strComputerName = WScript.Arguments.Named("Machine") 100:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 101: 102:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 103:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 104: 105:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 106:                                                     strUserID, strPassword) ...: 109:    Set objWMIInstances = objWMIServices.InstancesOf (cWMIClass) ...: 112:    If objWMIInstances.Count > 0 Then 113:       For Each objWMIInstance In objWMIInstances 114:           If boolViewProxy Then 115:              Set objWMIPropertySet = objWMIInstance.Properties_ 116:              For Each objWMIProperty In objWMIPropertySet 117:                  DisplayFormattedProperty objWMIInstance, _ 118:                                           "  " & objWMIProperty.Name, _ 119:                                           objWMIProperty.Name, _ 120:                                           Null 121:              Next ...: 124:           End If 125: 126:           If boolSetProxy Then 127:              intRC = objWMIInstance.SetProxySetting (strProxyAddress, intProxyPort) 128:              If Err.Number Then ErrorHandler (Err) 129: 130:              If intRC = 0 Then 131:                 WScript.Echo "Proxy settings successfuly udpated." 132:              Else 133:                 WScript.Echo "Failed to update Proxy settings (" & intRC & ")." 134:              End If 135:           End If 136:       Next 137:    End If ...: 143:    ]]> 144:    </script> 145:  </job> 146:</package> 

end example

Once command-line parsing completes (lines 62 through 100) and the WMI connection is executed (lines 102 through 106), the script retrieves all instances of the Win32_Proxy class (line 109). Since this class is not a singleton class, and because it uses the proxy settings as Key properties, the easiest way to retrieve the information is to start an enumeration of the available instances.

When the /ViewProxy+ switch is used, the script shows the current Windows Proxy settings (lines 114 through 124). This portion of code enumerates and displays all properties available from the Win32_Proxy class (lines 115 through 121). Once executed, the output will be as follows:

 C:\>WMIProxy.Wsf /ViewProxy+ Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.   ProxyPortNumber: ....................... 8080   ProxyServer: ........................... http://proxy.LissWare.Net   *ServerName: ........................... net-dpen6400a.LissWare.Net 

When the /ProxyAddress switch is supplied, the script invokes the SetProxySetting method of the Win32_Proxy class to configure the Windows Proxy LAN settings (line 127). This script is not really complicated; it simply takes advantage of the Win32_Proxy class capabilities.

3.3.8 Windows Product Activation provider

These providers manage the information related to the Windows Product Activation (WPA). The providers are implemented as instance and method providers (Table 3.17). Available for Windows XP and Windows Server 2003, the WPA is not supported on 64-bit Windows and previous Windows platforms.

Table 3.17: The Windows Product Activation Providers Capabilities

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

Performance Monitoring Provider

Win32_WIN32_COMPUTERSYSTEMWINDOWSPRODUCTACTIVATIONSETTING_Prov

Root/CIMV2

X

X

X

X

X

X

X

X

Win32_WIN32_WINDOWSPRODUCTACTIVATION_Prov

Root/CIMV2

X

X

X

X

X

X

X

X

Two classes are supported by the WMI providers and expose methods to perform Windows product activation. Table 3.18 lists the class names available, while Table 3.19 shows the methods exposed by the Win32_WindowsProductActivation class.

Table 3.18: The Windows Product Activation Providers Classes

Name

Type

Comments

Win32_WindowsProductActivation

Dynamic

The Win32_WindowsProductionActivation class contains properties and methods that relate to Windows Product Activation, such as: activation state, grace period, and provides the ability to activate the machine online and offline.

Win32_ComputerSystemWindowsProductActivationSetting

Association

This class represents an association between Win32_ComputerSystem and Win32_WindowsProductActivation

Table 3.19: The Windows Product Activation Providers Methods

Name

Comments

ActivateOffline

This function is a scriptable equivalent to manual telephone activation. It permits offine activation using the Confirmation ID provided by the Microsoft Clearinghouse. In order to complete offline activation, the InstallafionID for the machine must be retrieved by querying for the property. The method returns 0 on success and an error code otherwise.

ActivateOnline

The ActivateOnline method exchanges license-related data with the Microsoft Clearinghouse server and, if successful, completes system activation. It requires that the target machine be able to communicate through the Internet using the HTTPS protocol. If necessary, the SetProxySetting method should first be used to connect through a firewall The method returns 0 on success and an error code otherwise.

GetInstallationID

GetInstallationID gets the InstallationID property and comprises the Product ID and Hardware ID, and is identical to the Installation ID displayed on the telephone activation page. Installation ID must be provided to the Microsoft Clearinghouse to obtain the corresponding Confirmation ID, which is required for the ActivateOffline method.

SetNotification

SetNotification is a function that enables or disables Windows Product Activation Notification reminders. The method returns 0 on success (or if activation is not pending) and an error code otherwise. Notification reminders are enabled by default. Note that this method does not affect Logon or event log reminders, nor does it alter the need to activate the computer.

SetProductKey

SetProductKey permits a computer's Product Key (and therefore its ProductID) to be changed or corrected. Only Product Keys that are valid for the media type (i.e., retail, volume licensing, OEM) will be accepted. The method can only be used while ActivationRequired is 1. Product KeyProduct Key is a 25-character alphanumeric string formatted in groups of five characters separated by dashes.

Note that all methods are only usable if the Windows product is not activated. Once the activation is completed, none of the methods can be used. Because WPA relates to a single computer, the Win32_WindowsProductActivation class is associated with the Win32_ComputerSystem class, as shown in Figure 3.6.

click to expand
Figure 3.6: The Win32_WindowsProductActivation class is associated with the Win32_ComputerSystem class.

It is important to understand that WPA can be executed on line or off line. While on-line activation executes via the Internet, off-line activation is executed on the phone with a Microsoft representative. In this case, the customer must provide an installation ID. Sample 3.14 implements the script logic to perform both activation types. The command-line parameters exposed by this script are as follows:

 C:\>WMIWPA.wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIWPA.wsf [/ViewProxy[+|-]] [/ProxyAddress:value] [/ProxyPort:value] [/ViewWPA[+|-]]                   [/ActivateOffLine:value] [/ActivateOnLine:value] [/GetInstallationID:value]                   [/SetProductKey:value] [/SetNotification:value] [/Machine:value] [/User:value]                   [/Password:value] Options: ViewProxy         : View the proxy settings. ProxyAddress      : Name of the proxy server to configure. ProxyPort         : Port number configured on the computer for access to the proxy server specified. ViewWPA           : View the Windows Product Activation (WPA) settings. ActivateOffLine   : Activates the system offline using the confirmation ID provided by the Microsoft                     Clearinghouse license server. ActivateOnLine    : Exchanges license-related data with the Microsoft Clearinghouse license server;                     if the method succeeds, it activates the system. GetInstallationID : Retrieves the installation ID which is required to activate a system offline. SetProductKey     : Updates the system product key for a computer. SetNotification   : Enable the notification of Number of days remaining before activation of the                     system is required. Machine           : Determine the WMI system to connect to. (default=LocalHost) User              : Determine the UserID to perform the remote connection. (default=none) Password          : Determine the password to perform the remote connection. (default=none) Examples:       WMIWPA.Wsf /ViewProxy+       WMIWPA.Wsf /ProxyAddress:proxy.LissWare.Net /ProxyPort:8080       WMIWPA.Wsf /ViewWPA+       WMIWPA.Wsf /ActivateOffLine:[ConfirmationID]       WMIWPA.Wsf /ActivateOnLine       WMIWPA.Wsf /GetInstallationID       WMIWPA.Wsf /SetProductKEY:VVVVV-WWWWW-XXXXX-YYYYY-ZZZZZ       WMIWPA.Wsf /SetNotification+ 

Sample 3.14: Windows Product Activation

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  40:    </runtime>  41:  42:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" />  43:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  44:  45:    <object prog  reference="true"/>  46:    <object prog  />  47:  48:    <script language="VBscript">  49:    <![CDATA[  ..:  53:    Const cComputerName = "LocalHost"  54:    Const cWMINameSpace = "Root\CIMv2"  55:    Const cWMIProxyClass = "Win32_Proxy"  56:    Const cWMIWPAClass = "Win32_WindowsProductActivation"  ..:  89:    ' --------------------------------------------------------------------------------  90:    ' Parse the command line parameters  91:    If WScript.Arguments.Named.Count = 0 Then  92:       WScript.Arguments.ShowUsage()  93:       WScript.Quit  94:    End If ...: 145:    strComputerName = WScript.Arguments.Named("Machine") 146:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 147: 148:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 149:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 150: 151:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 152:                                                     strUserID, strPassword) ...: 186: 187:    ' --------------------------------------------------------------------------------- 188:    Set objWMIInstances = objWMIServices.InstancesOf (cWMIWPAClass) ...: 191:    If objWMIInstances.Count = 1 Then 192:       For Each objWMIInstance In objWMIInstances 193:           If boolViewWPA Then 194:           Set objWMIPropertySet = objWMIInstance.Properties_ 195:               For Each objWMIProperty In objWMIPropertySet 196:                   DisplayFormattedProperty objWMIInstance, _ 197:                                            " " & objWMIProperty.Name, _ 198:                                            objWMIProperty.Name, _ 199:                                            Null 200:               Next ...: 203:           End If 204:           If boolGetInstallationID Then 205:              If objWMIInstance.ActivationRequired = 1 Then 206:                 intRC = objWMIInstance.GetInstallationID (strInstallationID) ...: 209:                 If intRC = 0 Then 210:                    WScript.Echo "Installation ID is '" & strInstallationID & "'." 211:                 Else 212:                    WScript.Echo "Failed to get Installation ID (" & intRC & ")." 213:                 End If 214:              Else 215:                 WScript.Echo "Unable to get the Installation ID " & _ 216:                              "as the Windows activation is already completed." 217:              End If 218:           End If 219:           If boolActivateOffLine Then 220:              If objWMIInstance.ActivationRequired = 1 Then 221:                 intRC = objWMIInstance.ActivateOffline (strConfirmationID) ...: 224:                 If intRC = 0 Then 225:                    WScript.Echo "Windows successfuly activated (off-line)." 226:                 Else 227:                    WScript.Echo "Failed (" & intRC & ")." 228:                 End If 229:              Else 230:                 WScript.Echo "Unable to acticate Windows " & _ 231:                              "as the Windows activation is already completed." 232:              End If 233:           End If 234:           If boolActivateOnLine Then 235:              If objWMIInstance.ActivationRequired = 1 Then 236:                 intRC = objWMIInstance.ActivateOnline() ...: 239:                 If intRC = 0 Then 240:                    WScript.Echo "Windows successfuly activated (on-line)." 241:                 Else 242:                    WScript.Echo "Failed to activate Windows (" & intRC & ")." 243:                 End If 244:              Else 245:                 WScript.Echo "Unable to acticate Windows " & _ 246:                              "as the Windows activation is already completed." 247:              End If 248:           End If 249:           If boolSetProductKEY Then 250:              If objWMIInstance.ActivationRequired = 1 Then 251:                 intRC = objWMIInstance.SetProductKey (strProductKey) ...: 254:                 If intRC = 0 Then 255:                    WScript.Echo "'" & strProductKey & "' product key successfuly set." 256:                 Else 257:                    WScript.Echo "Failed setting '" & strProductKey & _ 258:                                 "' product key (" & intRC & ")." 259:                 End If 260:              Else 261:                 WScript.Echo "Unable to set the Product Key " & _ 262:                              "as the Windows activation is already completed." 263:              End If 264:           End If 265:           If Len (boolSetNotification) Then 266:              intRC = objWMIInstance.SetNotification (intSetNotificationWPA) ...: 269:              If intRC = 0 Then 270:                 If boolSetNotification Then 271:                    WScript.Echo "WPA Notification enabled." 272:                 Else 273:                    WScript.Echo "WPA Notification disabled." 274:                 End If 275:              Else 276:                 WScript.Echo "Failed to set WPA notification (" & intRC & ")." 277:              End If 278:           End If 279:       Next 280:    End If ...: 286:    ]]> 287:    </script> 288:  </job> 289:</package> 

end example

Because proxy settings could be required for an on-line activation, the script also uses the Win32_Proxy class to configure the Windows Proxy LAN settings. As we have previously seen in Sample 3.13, this portion of the code is skipped in Sample 3.14 (skipped lines 153 through 186).

Once the command-line parameter definitions (lines 13 through 40) and parsing (lines 89 through 146) with the WMI connection are completed (lines 148 through 152), the script executes the various operations supported by the Win32_WindowsProductActivation class (lines 188 through 280). First, independently of the WPA operation performed, the script retrieves all instances of the Win32_WindowsProductActivation class (line 188). This class is not implemented as a singleton class, but since we only have one instance of the WPA in a computer system, the script only considers the first instance available (line 191). The first supported script action displays the WPA information with the following command line:

 1:   C:\>WMIWPA.Wsf /ViewWPA+ 2:   Microsoft (R) Windows Script Host Version 5.6 3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. 4: 5:     ActivationRequired: .................... 1 6:     IsNotificationOn: ...................... 1 7:     ProductID: ............................. 55039-986-4602466-00615 8:     RemainingEvaluationPeriod: ............. 185 9:     RemainingGracePeriod: .................. 14 10:    *ServerName: ........................... NET-DPEP6400 

The script logic is shown from line 194 through 200 and does not contain any particular coding that we haven't seen before.

The next WPA-supported action is the retrieval of the InstallationID. When performing an off-line activation, the customer must provide an InstallationID to the Microsoft representative over the phone. The InstallationID can be retrieved with the following command line:

 C:\>WMIWPA.Wsf /GetInstallationID Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Installation ID is '00450052973083532694579966743296021641034484695370'. 

The script logic is available from line 204 through 217. It is important to note that the script tests the state of the activation by verifying the value contained in the ActivationRequired property (line 205). This verification is made for every WPA action, since the Win32_WindowsProductActivation methods are only executable when the product is not activated (lines 220, 235, and 250). Next, the GetInstallationID method is invoked. When the execution is successful (line 209), the parameter passed during the method invocation (line 206) contains the InstallationID required by the Microsoft representative.

In exchange, the Microsoft representative will provide another number, which is a ConfirmationID, that is required to perform the off-line activation. This is the next action supported by Sample 3.14. The following command line must be used:

 C:>WMIWPA.Wsf /ActivateOffLine:[ConfirmationID] Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Windows successfuly activated (off-line). 

The script logic is available from line 219 through 233. Although the script follows the same logic as before, it invokes the ActiveOffLine method, which requires the ConfirmationID as parameter (line 221).

The next WPA action performs the on-line Product Activation. In this case the command line to use is:

 C:\>WMIWPA.Wsf /ActivateOnLine Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Windows successfuly activated (on-line). 

The script logic is available from line 234 through 248. Again, the logic is exactly the same as before. However, the ActiveOnLine method does not require any parameter (line 236).

While the product key is given at installation time, the SetProductKey method of the Win32_WindowsProductActivation class allows the modification of the product key before activation. The following command line must be used with a valid product key:

 C:\>WMIWPA.Wsf /SetProductKEY:[VVVV-WWWWW-XXXXX-YYYYY-ZZZZZ] Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. 'VVVV-WWWWW-XXXXX-YYYYY-ZZZZZ' product key successfuly set. 

The script logic is available from line 249 through 264. The SetProductKey method requires the product key as a parameter (line 251).

If the product is not activated, the system sends notification of the remaining days before activation is mandatory. It is possible to enable or disable this notification with the script by using the following command line:

 C:\>WMIWPA.Wsf /SetNotification+ Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. WPA Notification enabled. 

Here again, the script logic for this action is exactly the same as the previous WPA operation (lines 265 through 278). The method to configure the notification is invoked at line 266. This method requests an integer value as parameter. A value of 0 means "disable" and a value of 1 means "enable."

3.3.9 Windows Installer provider

The Windows Installer provider is not always available by default for all Windows platforms! To install this provider, you should perform the following tasks:

  • For Windows XP: It is included in the system installation by default.

  • For Windows Server 2003: From Control Panel, select Add/Remove Programs. Next, select Add/Remove Windows Components; then, in the Windows Components Wizard, select Management and Monitoring Tools (see Figure 3.7).

    click to expand
    Figure 3.7: Adding the Windows Installer provider under Windows Server 2003.

Finally, select WMI Windows Installer provider, and then click OK. Follow the steps in the wizard to complete the installation.

  • For Windows 2000 and Windows NT 4.0: The Windows Installer package for Windows NT 4.0 and 2000 is available at http://www.microsoft.com/downloads/release.asp?releaseid=32832.

The WMI Windows Installer provider allows WMI-enabled scripts or applications to access information collected from Windows Installer-compliant applications. The provider mirrors the functionality of the Windows Installer. It can read any property of a software product installation. In addition, due to the WMI architecture, the Windows Installer provider makes available to remote users the set of procedures that the Windows Installer makes available to local users. This provider is implemented as an instance and a method provider (Table 3.20).

Table 3.20: The Windows Installer Provider

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

Windows Installer Provider

MSIProv

Root/CIMV2

X

X

X

X

X

X

X

X

X

X

X

The Windows Installer supports more than 50 classes. Unfortunately, it is beyond the scope of this book to review all the classes. Instead, we will give an overview of the most important classes available with their capabilities. The classes supported by the WMI Windows Installer provider can be classified into six categories.

  • Actions: This category contains the classes derived from the CIM_Action abstract class and represents actions performed during installation, upgrade, uninstall, or application maintenance.

  • Associations: This category contains the association classes that represent references to other WMI Windows Installer provider classes.

  • Checks: This category contains the classes derived from the CIM_ Check abstract class and represents conditions that should be met when a software feature or element is installed.

  • Core Classes: This category contains the most important classes, because it provides most of the software installation features.

  • External Associations: This category contains the association classes that represent the references to Win32 classes beyond the scope of the Windows Installer provider classes.

  • Settings: This category contains the classes that represent instances of settings containing additional information about installations or their components.

Table 3.21 summarizes by category the WMI classes related to the Windows Installer.

Table 3.21: The Windows Installer WMI Classes

Name

Comments

Actions

Win32_BindlmageAction

The Bindlmage action binds each executable that needs to be bound to the DLLs imported by it by computing the virtual address of each function that is imported from all DLLs. The computed virtual address is then saved in the importing image's Import Address Table (IAT). The action works on each file installed locally.

Win32_ClassInfoAction

The RegisterClassInfo action manages the registration of COM class information with the system. In the Advertise mode the action registers all COM classes for which the corresponding feature is enabled. Else the action registers COM classes for which the corresponding feature is currently selected to be installed.

Win32_CreateFolderAction

The CreateFolder action creates empty folders for components set to be installed locally. The removal of these folders is handled by the RemoveFolders action. When a folder is newly-created, it is registered with the appropriate component identifier.

Win32_DuplicateFileAction

The DuplicateFileAction allows the author to make one or more duplicate copies of files installed by the InstallFiles executable action, either to a directory different from the original file, or to the same directory, but with a different name.

Win32_ExtensionInfoAction

The ExtensionInfoAction manages the registration of extension-related information with the system. The action registers the extension servers for which the corresponding feature is currently selected to be uninstalled.

Win32_FontInfoAction

The RegisterFonts action registers installed fonts with the system. It maps the Font.FontTitle to the path of the font file installed. The RegisterFonts action is triggered when the Component to which the Font.File_ belongs is selected for install. This implies that fonts can be made private, shared or system by making the Components to which they belong so.

Win32_MIMEInfoAction

The RegisterMIMEInfo action registers the MIME-related registry information with the system. In the Advertise mode the action registers all MIME info for servers for which the corresponding feature is enabled. Else the action registers MIME info for servers forwhich the corresponding feature is currently selected to be installed.

Win32_MoveFileAction

The MoveFiles action allows the author to locate files that already exist on the user's machine, and move or copy those files to a new location.

Win32_PublishComponentAction

The PublishComponents action manages the advertisement of the components that may be faulted in by other products with the system. In the Advertise mode the action publishes the all components for which the corresponding feature is enabled. Else the action publishes components for which the corresponding feature is currently selected to be installed.

Win32_RegistryAction

The WriteRegistryValues action sets up registry information that the application desires in the system Registry. The registry information is gated by the Component class. A registry value is written to the system registry if the corresponding component has been set to be installed either locally or run from source.

Win32_RemoveFileAction

The RemoveFiles action uninstalls files previously installed by the InstallFiles action. Each of these files is 'gated' by a link to an entry in the Component class; only those files whose components are resolved to the iisAbsent Action state, or the iisSource Action state IF the component is currently installed locally, will be removed. The Remove Files action can also remove specific author-specified files that weren't installed by the InstallFiles action. Each of these files is 'gated' by a link to an entry in the Component class; those files whose components are resolved to any 'active' Action state (i.e. not in the 'off', or NULL, state) will be removed (if the file exists in the specified directory, of course). This implies that removal of files will be attempted when the gating component is first installed, during a reinstall, and again when the gating component is removed.

Win32_RemoveIniAction

The RemoveIniValues action deletes .INI file information that the application desires to delete from .INI files. The deletion of the information is gated by the Component class. An .INI value is deleted if the corresponding component has been set to be installed either locally or run from source.

Win32_SelfRegModuleAction

The SelfRegModules action processes all the modules in the SelfReg to register the modules, if installed.

Win32_ShortcutAction

The CreateShortcuts action manages the creation of shortcuts. In the Advertise mode, the action creates shortcuts to the key files of components of features that are enabled. Advertised shortcuts are those for which the Target property is the feature of the component and the directory of the shortcut is one of the Shell folders or below one. Advertised shortcuts are created with a Microsoft installer technology Descriptor as the target. Non-advertised shortcuts are those for which the Target column in the Shortcut class is a property or the directory of the shortcut is not one of the Shell folders or below one. Advertised shortcuts are created with a Microsoft installer technology Descriptor as the target. In the non-advertise mode (normal install) the action creates shortcuts to the key files of components of features that are selected for install as well as non-advertised shortcuts whose component is selected for install.

Win32_TypeLibraryAction

The RegisterTypeLibraries action registers type libraries with the system. The action works on each file referenced which is triggered to be installed.

Associations

Win32_ActionCheck

This association relates an MSI action with any locational information it requires. This location is in the form of a file and/or directory specification.

Win32_ApplicationCommandLine

The ApplicationCommandLine association allows one to to identify connection between an application and its command-line access point.

Win32_CheckCheck

This association relates a MSI Check with any locational information it requires. The location is in the form of a file and/or directory specification.

Win32_ODBCDriverSoftwareElement

Since software elements in a ready to run state cannot transition into another state, the value of the phase property is restricted to in-state for CIM_SoftwareElement objects in a ready to run state.

Win32_ProductCheck

This association relates instances of CIM_Check and Win32 Product.

Win32_ProductResource

This association relates instances of Win32 Product and Win32_MSIResource.

Win32_ProductSoftwareFeatures

The CIM_ProductSoftwareFeatures association identifies the software features for a particular product.

Win32_SettingCheck

This association relates an Installer check with any setting information it requires.

Win32_ShortcutSAP

This association relates the connection between an application access point and the corresponding shortcut.

Win32_SoftwareElementAction

This association relates an MSI software element with an action that accesses the element.

Win32_SoftwareElementCheck

This association relates an MSI element with any condition or locational information that a feature may require.

Win32_SoftwareElementResource

This association relates an MSI feature with an action used to register and/or publish the feature.

Win32_SoftwareFeatureAction

This association relates an MSI feature with an action used to register and/or publish the feature.

Win32_SoftwareFeatureCheck

This association relates an MSI feature with any condition or locational information that a feature may require.

Win32_SoftwareFeatureParent

A generic association to establish dependency relationships between objects.

Win32_SoftwareFeatureSoftwareElements

CIM_Component is a generic association used to establish 'part of relationships between Managed System Elements. For example, the SystemComponent association defines parts of a System.

Core

Win32_Product

Instances of this class represent products as they are installed by MSI. A product generally correlates to a single installation package.

Win32_SoftwareElement

SoftwareFeatures and SoftwareElements: A 'SoftwareFeature' is a distinct subset of a Product, consisting of one or more 'SoftwareElements'. Each SoftwareElement is defined in a Win32_SoftwareElement instance, and the association between a feature and its SoftwareFeature(s) is defined in the Win32_SoftwareFeatureSoftwareElement Association. Any component can be 'shared' between two or more SoftwareFeatures. If two or more features reference the same component, that component will be selected for installation if any of these features are selected.

Win32_SoftwareFeature

SoftwareFeatures and SoftwareElements: A 'SoftwareFeature' is a distinct subset of a Product, consisting of one or more 'SoftwareElements'. Each SoftwareElement is defined in a Win32_SoftwareElement instance, and the association between a feature and its SoftwareFeature(s) is defined in the Win32_SoftwareFeatureSoftwareElement Association. Any component can be 'shared' between two or more SoftwareFeatures. If two or more features reference the same component, that component will be selected for installation if any of these features are selected.

Checks

Win32_Condition

The Condition class can be used to modify the selection state of any entry in the Feature class, based on a conditional expression. If Condition evaluates to True, the corresponding Level value in the Feature class will be set to the value specified in the Condition class's Level column. Using this mechanism, any feature can be permanently disabled (by setting the Level to 0), set to be always installed (by setting the Level to 1), or set to a different install priority (by setting Level to an intermediate value). The Level may be set based upon any conditional statement, such as a test for platform, operating system, a particular property setting, etc.

Win32_DirectorySpecification

This class represents the directory layout for the product. Each instance of the class represents a directory in both the source image and the destination image. Directory resolution is performed during the CostFinalize action and is done as follows: Root destination directories: Root directories entries are those with a null Directory_Parent value or a irectory_Parent value identical to the Directory value. The value in the Directory property is interpreted as the name of a property defining the location of the destination directory. If the property is defined, the destination directory is resolved to the property's value. If the property is undefined, the ROOTDRIVE property is used instead to resolve the path. Root source directorires: The value of the DefaultDir column for root entries is interpreted as the name of a property defining the source location of this directory. This property must be defined or an error will occur. Non-root destination directories: The Directory value for a non-root directory is also interpreted as the name of a property defining the location of the destination. If the property is defined, the destination directory is resolved to the property's value. If the property is not defined, the destination directory is resolved to a sub-directory beneath the resolved destination directory for the Directory_Parent entry. The DefaultDir value defines the name of the sub-directory. Non-root source directories: The source directory for a non-root directory is resolved to a sub-directory of the resolved source directory for the Directory_Parent entry. Again, the DefaultDirvalue defines the name of the sub-directory.

Win32_EnvironmentSpecification

Instances of this class contain information about any environment variables that may need to be registered for their associated products installation.

Win32_FileSpecification

Each instance of this class represents a source file with itsvarious attributes, ordered by a unique, nonlocalized identifier. For uncompressed files, the File property is ignored, and the FileName column is used for both the source and destination file name. You must set the 'Uncompressed' bit of the Attributes column for any file that is not compressed in a cabinet.

Win32_IniFileSpecification

This class contains the .INI information that the application needs to set in an .INI file. The .INI file information is written out when the corresponding component has been selected to be installed, either locally or run from source.

Win32_LaunchCondition

The LaunchCondition class is used by the LaunchConditions action. It contains a list of conditions, all of which must be satisfied for the action to succeed.

Win32_ODBCDataSourceSpecification

This association relates an MSI check with any setting information it requires.

Win32_ODBC DriverSpecification

This class represents any ODBC drivers that are to be installed as part of a particular product.

Win32_ODBCTranslatorSpecification

Instances of this class represent any ODBC Translators that are included as part of a products installation.

Win32_ProgIDSpecification

Instances of this class represent and ProgIDs that need to be registered durring a given installation.

Win32_ReserveCost

This optional class allows the author to 'reserve' a specified amount of disk space in any directory, depending on the installation state of a component. Reserving cost in this way could be useful for authors who want to ensure that a minimum amount of disk space will be available after the installation is completed. For example, this disk space might be reserved for user documents, or for application files (such as index files) that are created only after the application is launched following installation. The ReserveCost class also allows custom actions to specify an approximate cost for any files, registry entries, or other items, that the custom action might install.

Win32_ServiceSpecification

Instances of this class represent the services that are to be installed along with an associated package.

Win32_SoftwareElementCondition

Instances of this class represent conditional checks that must be evaluated to TRUE before their associated Win32 Software Element can be installed.

External Associations

Win32_InstalledSoftwareElement

The InstalledSoftwareElement association allows one to to identify the Computer System a particular Software element is installed on.

Win32_SetviceSpecificationService

Represents instances of Win32_ServiceSpecification and Win32_Service.

Settings

Win32_Binary

Instances of this class represent binary information (such as bitmaps, icons, executables, etc.) that are used by an installation.

Win32_MSIResource

Represents any resources that are used by the Installer during the course of an installation, patch, or upgrade.

Win32_ODBCAttribute

The Setting class represents configuration-related and operational parameters for one or more ManagedSystemElement(s). A ManagedSystemElement may have multiple Setting objects associated with it. The current operational values for an Element's parameters are reflected by properties in the Element itself or by properties in its associations. These properties do not have to be the same values present in the Setting object. For example, a modem may have a Setting baud rate of 56Kb/sec but be operating at 19.2Kb/sec.

Win32_ODBCSourceAttribute

The Setting class represents configuration-related and operational parameters for one or more ManagedSystemElement(s). A ManagedSystemElement may have multiple Setting objects associated with it. The current operational values for an Element's parameters are reflected by properties in the Element itself or by properties in its associations. These properties do not have to be the same values present in the Setting object. For example, a modem may have a Setting baud rate of 56Kb/sec but be operating at 19.2Kb/sec.

Win32_Patch

Instances of this class represent individual patches that are to be applied to a particular file and whose source resides at a specified location.

Win32_PatchPackage

The PatchPackage class describes all patch packages that have been applied to this product. For each patch package, the unique identifier for the patch is provided, along with information about the media image the on which the patch is located.

Win32_Property

This table contains the property names and values for all defined properties in the installation. Properties with Null values are not present in the table.

Win32_ServiceControl

Instances of this class represent instructions for controlling both installed and uninstalled services.

The easiest way to get an immediate benefit from the Windows Installer via WMI is to work with the Win32_Product class. This class represents the Windows Installer-compliant products installed in a system. This class exposes seven methods with some parameters (Table 3.22).

Table 3.22: The Win32_Product Class Methods

Method name

Comments

Admin

  • PackageLocation

The path to the package that is to be administrated.

  • Target Location

The location for the administrative image to be installed.

  • Options

The command-line options for the upgrade.

Advertise

  • PackageLocation

The path to the package that is to be administrated.

  • Options

The command-line options for the upgrade.

  • AllUsers

Indicates whether the operation should be applied to the current user (FALSE) or all users on the machine (TRUE).

Configure

  • InstallState

Default, Local, Source

  • InstallLevel

Default, Minimum, Maximum

Install

  • PackageLocation

The path to the package that is to be administrated.

  • Options

The command-line options for the upgrade.

  • AllUsers

Indicates whether the operation should be applied to the current user (FALSE) or all users on the machine (TRUE).

Reinstall

  • ReinstallMode

Perform the package installation in the specified mode. The mode can be one of the following values: FileMissing (1), FileOlderVersion (2), FileEqualVersion (3), FileExact (4), FileVerify (5), FileReplace (6), UserData (7), MachineData(8), Shortcut (9), Package (10).

Uninstall

  • -

Upgrade

  • PackageLocation

The command-line options for the upgrade.

  • Options

Indicates whether the operation should be applied to the current user (FALSE) or all users on the machine (TRUE).

Samples 3.15 through 3.17 illustrate the use of the Win32_Product methods. The script exposes the following command-line parameters:

 C:\>WMIMSI.Wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIMSI.wsf [/Action:value] [/SoftwareFeature[+|-]] [/PackageLocation:value] [/Options:value]                                   [/AllUsers[+|-]] [/TargetLocation:value] [/ReInstallMode:value]                                   [/PackageName:value] [/PackageVersion:value]                                   [/Machine:value] [/User:value] [/Password:value] Options: Action          : Windows Installer action to perform. Only [View], [Install], [Admin], [Advertise],                   [ReInstall], [UnInstall] or [Upgrade]is accepted. SoftwareFeature : View software features associated with the Windows Installer package                   (View action only). PackageLocation : Defines the Windows Installer package source path                   (Install, Admin, Advertise and Upgrade actions only). Options         : Command line options for the installation. AllUsers        : Specifies if the package is installed for All Users                   (Install and Advertise actions only). TargetLocation  : Defines the Windows Installer package admin installation path target                   (Admin action only). ReInstallMode   : Defines the package reinstallation mode (Reinstall action only). PackageName     : Name of the package (Reinstall, Upgrade and Uninstall action only). PackageVersion  : Version of the package (Reinstall, Upgrade and Uninstall action only). Machine         : Determine the WMI system to connect to. (default=LocalHost) User            : Determine the UserID to perform the remote connection. (default=none) Password        : Determine the password to perform the remote connection. (default=none) Examples:       WMIMSI.Wsf /Action:View       WMIMSI.Wsf /Action:View /SoftwareFeature+       WMIMSI.Wsf /Action:Install /PackageLocation:L:\SUPPORT\TOOLS\SUPTOOLS.MSI /AllUsers+       WMIMSI.Wsf /Action:Admin /PackageLocation:L:\SUPPORT\TOOLS\SUPTOOLS.MSI                                /TargetLocation:"E:\SUPTOOLS"       WMIMSI.Wsf /Action:Advertise /PackageLocation:L:\SUPPORT\TOOLS\SUPTOOLS.MSI /AllUsers+       WMIMSI.Wsf /Action:ReInstall /ReinstallMode:Shortcut /PackageName:"Windows Support Tools"                                    /PackageVersion:"5.1.2510.0"       WMIMSI.Wsf /Action:Upgrade /PackageLocation:L:\SUPPORT\TOOLS\SUPTOOLS.MSI                                  /PackageName:"Windows Support Tools" /PackageVersion:"5.1.2510.0"       WMIMSI.Wsf /Action:UnInstall /PackageName:"Windows Support Tools" /PackageVersion:"5.1.2510.0" 

Sample 3.15: Managing Windows Installer packages (Part I)

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  39:    </runtime>  40:  41:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodeInstallStateFunction.vbs" />  42:  43:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" />  44:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  45:  46:    <object prog  reference="true"/>  47:    <object prog  />  48:  49:    <script language="JScript">  50:    <![CDATA[  51:  52:    var cComputerName = "LocalHost";  53:    var cWMINameSpace = "Root/CIMv2";  54:    var cWMIClass = "Win32_Product";  55:  56:    var cVIEW = 1;  57:    var cADMIN = 2;  58:    var cADVERTISE = 3;  59:    var cINSTALL = 4;  60:    var cREINSTALL = 5;  61:    var cUNINSTALL = 6;  62:    var cUPGRADE = 7;  ..:  92:    // --------------------------------------------------------------------------------  93:    // Parse the command line parameters  94:    if (WScript.Arguments.Named.Count == 0)  95:       {  96:       WScript.Arguments.ShowUsage();  97:       WScript.Quit();  98:       } ...: 242:    strComputerName = WScript.Arguments.Named("Machine"); 243:    if (strComputerName == null) 244:       { 245:       strComputerName = cComputerName; 246:       } 247: 248:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault; 249:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate; 250: 251:    try 252:      { 253:      objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, 254:                                                   strUserID, strPassword); 255:      } ...: 261:    switch (intAction) 262:           { 263:           // VIEW ---------------------------------------------------------------------------- 264:           case cVIEW: 265:                try 266:                  { 267:                  objWMIInstances = objWMIServices.InstancesOf (cWMIClass); 268:                  } ...: 274:                enumWMIInstances = new Enumerator (objWMIInstances); 275:                for (;! enumWMIInstances.atEnd(); enumWMIInstances.moveNext()) 276:                    { 277:                    objWMIInstance = enumWMIInstances.item(); 278: 279:                    WScript.Echo ("- " + objWMIInstance.Caption + " " + strDashes); 280:                    objWMIPropertySet = objWMIInstance.Properties_; 281:                    enumWMIPropertySet = new Enumerator (objWMIPropertySet); 282:                    for (;! enumWMIPropertySet.atEnd(); enumWMIPropertySet.moveNext()) 283:                        { 284:                        objWMIProperty = enumWMIPropertySet.item(); 285: 286:                        switch (objWMIProperty.Name) 287:                               { 288:                               case "Caption": 289:                                    break; 290: 291:                               case "InstallState": 292:                                    DisplayFormattedProperty (objWMIInstance, 293:                                           " " + objWMIProperty.Name, 294:                                           InstallState (objWMIProperty.Value), 295:                                           null); 296:                                    break; 297:                               default: 298:                                    DisplayFormattedProperty (objWMIInstance, 299:                                           " " + objWMIProperty.Name, 300:                                           objWMIProperty.Name, 301:                                           null); 302:                               } 303:                        } 304: 305:                    if (boolSoftwareFeature) 306:                       { 307:                       try 308:                         { 309:                         objWMIAssocInstances = objWMIServices.ExecQuery 310:                            ("Associators of {" + 311:                            objWMIInstance.Path_.RelPath + "} Where " + 312:                            "ResultClass=Win32_SoftwareFeature"); 313:                         } ...: 319:                       if (objWMIAssocInstances.Count != 0) 320:                          { 321:                          enumWMIAssocInstances = new Enumerator (objWMIAssocInstances); 322:                          for(;!enumWMIAssocInstances.atEnd();enumWMIAssocInstances.moveNext()) 323:                              { 324:                              objWMIAssocInstance = enumWMIAssocInstances.item(); 325: 326:                              WScript.Echo ("\n - Software feature for '" + 327:                                           objWMIInstance.Caption + "' " + strDashes); 328:                              objWMIPropertySet = objWMIAssocInstance.Properties_; 329:                              enumWMIPropertySet = new Enumerator (objWMIPropertySet); 330:                         for(;! enumWMIPropertySet.atEnd(); enumWMIPropertySet.moveNext()) 331:                                  { 332:                                  objWMIProperty = enumWMIPropertySet.item(); 333: 334:                                  switch (objWMIProperty.Name) 335:                                         { 336:                                         case "Caption": 337:                                              break; 338: 339:                                         case "InstallState": 340:                                              DisplayFormattedProperty (objWMIAssocInstance, 341:                                                     " " + objWMIProperty.Name, 342:                                                     InstallState (objWMIProperty.Value), 343:                                                     null); 344:                                              break; 345:                                         default: 346:                                              DisplayFormattedProperty (objWMIAssocInstance, 347:                                                     " " + objWMIProperty.Name, 348:                                                     objWMIProperty.Name, 349:                                                     null); 350:                                         } 351:                                  } 352:                              } 353:                          } 354:                       } 355: 356:                    WScript.Echo(); 357:                    } 358: 359:                break; ...: ...: ...: 

end example

The first portion of the script is shown in Sample 3.15. Written in Jscript, and similar to previous scripts, this sample starts with the command-line parameter definitions (skipped lines 13 through 39) and parsing (skipped lines 92 through 246). Next, it contains the coding logic to display information about the installed Windows Installer-compliant applications (lines 263 through 359).

Although Jscript is used, the logic from a WMI standpoint is exactly the same as used in many previous scripts. The script requests the collection of instances available from the Win32Product class (line 267). Next, it creates an enumerator object to display properties of each Win32Product instance (lines 280 through 303). If the SoftwareFeature+ switch is given on the command line, the script displays some extra information from the Win32_SoftwareFeature class, which is associated with the Win32Product class (Figure 3.8).

click to expand
Figure 3.8: The classes associated with the Win32_Product class.

Once the collection of associated instances is created, the properties of each associated instance available in the collection are displayed (lines 306 through 354).

The result obtained for the Microsoft Support Tools Windows Installer package is as follows:

  1: C:\>WMIMSI.Wsf /Action:View /SoftwareFeature+ /Machine:MyRemoteSystem.LissWare.Net  2: Microsoft (R) Windows Script Host Version 5.6  3: Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   - Windows Support Tools --------------------------------------------------------------------  6:     Description: ......................... Windows Support Tools  7:     *IdentifyingNumber: .................. {8398B542-3CC4-44D9-83DF-696CCE70124B}  8:     InstallDate: ......................... 20020127  9:     InstallDate2: ........................ 27-01-2002 10:     InstallState: ........................ Installed 11:     *Name: ............................... Windows Support Tools 12:     PackageCache: ........................ C:\WINDOWS\Installer\566eb2.msi 13:     Vendor: .............................. Microsoft Corporation 14:     *Version: ............................ 5.1.2510.0 15: 16:     - Software feature for 'Windows Support Tools' ------------------------------------------- 17:     Accesses: ............................ 0 18:     Attributes: .......................... 17 19:     Description: ......................... Minimum tools that would be installed. 20:     *IdentifyingNumber: .................. {8398B542-3CC4-44D9-83DF-696CCE70124B} 21:     InstallDate: ......................... 27-01-2002 22:     InstallState: ........................ Local 23:     LastUse: ............................. 19800000******.000000+*** 24:     *Name: ............................... FeRequired 25:     *ProductName: ........................ Windows Support Tools 26:     Vendor: .............................. Microsoft Corporation 27:     *Version: ............................ 5.1.2510.0 28: 29:     - Software feature for 'Windows Support Tools' ------------------------------------------- 30:     Accesses: ............................ 0 31:     Attributes: .......................... 17 32:     Description: ......................... Windows Support Tools 33:     *IdentifyingNumber: .................. {8398B542-3CC4-44D9-83DF-696CCE70124B} 34:     InstallState: ........................ Local 35:     LastUse: ............................. 19800000******.000000+*** 36:     *Name: ............................... FeFullKit 37:     *ProductName: ........................ Windows Support Tools 38:     Vendor: .............................. Microsoft Corporation 39:     *Version: ............................ 5.1.2510.0 40: 41:     - Software feature for 'Windows Support Tools' ------------------------------------------- 42:     Accesses: ............................ 0 43:     Attributes: .......................... 17 44:     Description: ......................... These are all optional tools. 45:     *IdentifyingNumber: .................. {8398B542-3CC4-44D9-83DF-696CCE70124B} 46:     InstallState: ........................ Absent 47:     LastUse: ............................. 19800000******.000000+*** 48:     *Name: ............................... FeOptional 49:     *ProductName: ........................ Windows Support Tools 50:     Vendor: .............................. Microsoft Corporation 51:     *Version: ............................ 5.1.2510.0 

Because WMI is DCOM based, it is possible to access the information available from a remote Windows Installer instance. This remains valid for any methods exposed by the Win32_Product class. The next portion of the script sample (Sample 3.16) addresses the Installation, the Admin Installation, and the Advertisement of a Windows Installer-compliant application. The use of these methods in combination with the /Machine switch and the /User and /Password switches allows the installation of the Windows Installer package on a remote computer from the command line. This is exactly where WMI leverages the power of the Windows Installer, since the Windows Installer is local only.

Sample 3.16: Managing Windows Installer packages (Part II)

start example

 ...: ...: ...: 359:                 break; 360:            // INSTALL ------------------------------------------------------------------------- 361:            case cINSTALL: 362:                 objWMIClass = objWMIServices.Get (cWMIClass); 363:                 WScript.Echo ("Installing ..."); 364: 365:                 intRC = objWMIClass.Install (strPackageLocation, 366:                                              strOptions, 367:                                              boolAllUsers); 368:                 if (intRC == 0) 369:                    { 370:                    WScript.Echo ("Package '" + strPackageLocation + " successfuly installed."); 371:                    } 372:                 else 373:                    { 374:                    WScript.Echo ("Failed to install package '" + strPackageLocation + 375:                                 "' (" + intRC + ")."); 376:                    } 377: 378:                 break; 379:           // ADMIN ---------------------------------------------------------------------------- 380:           case cADMIN: 381:                objWMIClass = objWMIServices.Get (cWMIClass); 382:                WScript.Echo ("Installing ..."); 383: 384:                intRC = objWMIClass.Admin (strPackageLocation, 385:                                           strTargetLocation, 386:                                           strOptions); 387:                if (intRC == 0) 388:                   { 389:                   WScript.Echo ("Admin installation of package '" + strPackageLocation + 390:                                "' successfuly completed."); 391:                   } 392:                else 393:                   { 394:                   WScript.Echo ("Failed to install package '" + strPackageLocation + 395:                                "' (" + intRC + ")."); 396:                   } 397: 398:                break; 399:           // ADVERTISE ----------------------------------------------------------------------- 400:           case cADVERTISE: 401:                objWMIClass = objWMIServices.Get (cWMIClass); 402:                WScript.Echo ("Advertising ..."); 403: 404:                intRC = objWMIClass.Advertise (strPackageLocation, 405:                                               strTargetLocation, 406:                                               boolAllUsers); 407:                if (intRC == 0) 408:                   { 409:                   WScript.Echo ("Package '" + strPackageLocation + 410:                                 "' successfuly advertised."); 411:                   } 412:                else 413:                   { 414:                   WScript.Echo ("Failed to advertise package '" + strPackageLocation + 415:                                 "' (" + intRC + ")."); 416:                   } 417: 418:                break; ...: ...: ...: 

end example

Because these three operations do not relate to a specific application package, the three Win32_Product methods ("Install," "Admin," and "Advertise") are defined in the CIM repository as static methods (Static qualifier). This justifies the class instance creation at line 362 for the Installation, at line 381 for the Admin Installation, and at line 401 for the Advertisement. For these three operations, the script logic is exactly the same in each case. Based on the command-line parameters given, the corresponding method with its set of parameters is invoked. Note that the /Options command-line parameter corresponds to some optional command-line parameters specific to the Windows Installer-compliant package (see Table 3.22).

The last portion of the script is shown in Sample 3.17 and shows the script logic to use the Reinstall, the Uninstall, and the Upgrade methods of the Win32_Product class. Note that these methods are specific to a Win32_ Product instance. This is why the script starts by retrieving the Windows Installer application that corresponds to the /PackageName and /Package-Version command-line switches (lines 423 through 426 for the "Reinstall," lines 467 through 470 for the "Uninstall," and lines 511 through 514 for the "Upgrade").

Sample 3.17: Managing Windows Installer packages (Part III)

start example

 ...: ...: ...: 418:                 break; 419:            // REINSTALL ----------------------------------------------------------------------- 420:            case cREINSTALL: 421:                 try 422:                   { 423:                   objWMIInstances = objWMIServices.ExecQuery 424:                                                 ("Select * From " + cWMIClass + 425:                                                 " Where Name='" + strPackageName + 426:                                                 "' And Version='" + strPackageVersion + "'"); 427:                   } ...: 433:                 if (objWMIInstances.Count != 0) 434:                    { 435:                    WScript.Echo ("Found package '" + strPackageName + 436:                                  "' (" + strPackageVersion + ") ... Reinstalling ..."); 437: 438:                    enumWMIInstances = new Enumerator (objWMIInstances); 439:                    for (;! enumWMIInstances.atEnd(); enumWMIInstances.moveNext()) 440:                        { 441:                        objWMIInstance = enumWMIInstances.item(); 442: 443:                        intRC = objWMIInstance.ReInstall (intReinstallMode); 444:                        if (intRC == 0) 445:                           { 446:                           WScript.Echo ("Package '" + strPackageName + 447:                                         "' successfuly reinstalled."); 448:                           } 449:                        else 450:                           { 451:                           WScript.Echo ("Failed to reinstall package '" + strPackageName + 452:                                         "' (" + intRC + ")."); 453:                           } 454:                        } 455:                    } 456:                 else 457:                    { 458:                    WScript.Echo ("Package '" + strPackageName + 459:                                  "' (" + strPackageVersion + ") not found."); 460:                    } 461: 462:                 break; 463:            // UNINSTALL ----------------------------------------------------------------------- 464:            case cUNINSTALL: 465:                 try 466:                   { 467:                   objWMIInstances = objWMIServices.ExecQuery 468:                                                 ("Select * From " + cWMIClass + 469:                                                  " Where Name='" + strPackageName + 470:                                                  "' And Version='" + strPackageVersion + "'"); 471:                   } ...: 477:                 if (objWMIInstances.Count != 0) 478:                    { 479:                    WScript.Echo ("Found package '" + strPackageName + 480:                                  "' (" + strPackageVersion + ") ... Uninstalling ..."); 481: 482:                    enumWMIInstances = new Enumerator (objWMIInstances); 483:                    for (;! enumWMIInstances.atEnd(); enumWMIInstances.moveNext()) 484:                        { 485:                        objWMIInstance = enumWMIInstances.item(); 486: 487:                        intRC = objWMIInstance.UnInstall(); 488:                        if (intRC == 0) 489:                           { 490:                           WScript.Echo ("Package '" + strPackageName + 491:                                         "' successfuly uninstalled."); 492:                           } 493:                        else 494:                           { 495:                           WScript.Echo ("Failed to uninstall package '" + strPackageName + 496:                                         "' (" + intRC + ")."); 497:                           } 498:                        } 499:                    } 500:                 else 501:                    { 502:                    WScript.Echo ("Package '" + strPackageName + 503:                                  "' (" + strPackageVersion + ") not found."); 504:                    } 505: 506:                 break; 507:            // UPGRADE ------------------------------------------------------------------------- 508:            case cUPGRADE: 509:                 try 510:                   { 511:                   objWMIInstances = objWMIServices.ExecQuery 512:                                                 ("Select * From " + cWMIClass + 513:                                                 " Where Name='" + strPackageName + 514:                                                 "' And Version='" + strPackageVersion + "'"); 515:                   } ...: 521:                 if (objWMIInstances.Count != 0) 522:                    { 523:                    WScript.Echo ("Found package '" + strPackageName + 524:                                  "' (" + strPackageVersion + ") ... Upgrading ..."); 525: 526:                    enumWMIInstances = new Enumerator (objWMIInstances); 527:                    for (;! enumWMIInstances.atEnd(); enumWMIInstances.moveNext()) 528:                        { 529:                        objWMIInstance = enumWMIInstances.item(); 530: 531:                        intRC = objWMIInstance.Upgrade (strPackageLocation, 532:                                                        strOptions); 533:                        if (intRC == 0) 534:                           { 535:                           WScript.Echo ("Package '" + strPackageLocation + 536:                                         "' successfuly upgraded."); 537:                           } 538:                        else 539:                           { 540:                           WScript.Echo ("Failed to upgrade package '" + strPackageName + 541:                                         "' (" + intRC + ")."); 542:                           } 543:                        } 544:                    } 545:                 else 546:                    { 547:                    WScript.Echo ("Package '" + strPackageName + 548:                                  "' (" + strPackageVersion + ") not found."); 549:                    } 550:           } ...: 552:    ]]> 553:    </script> 554:  </job> 555:</package> 

end example

Whether the requested Windows Installer action is to reinstall, uninstall, or upgrade an existing package, the script always uses the same technique. It is important to note that the Win32_Product key uses three properties as a key. The following output shows the three keys (lines 7, 11, and 14):

  1:  C:\>WMIMSI.Wsf /Action:View /SoftwareFeature+ /Machine:MyRemoteSystem.LissWare.Net  2:  Microsoft (R) Windows Script Host Version 5.6  3:  Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:  - Windows Support Tools --------------------------------------------------------------------  6:    Description: ........................... Windows Support Tools  7:    *IdentifyingNumber: .................... {8398B542-3CC4-44D9-83DF-696CCE70124B}  8:    InstallDate: ........................... 20020127  9:    InstallDate2: .......................... 27-01-2002 10:    InstallState: .......................... Installed 11:    *Name: ................................. Windows Support Tools 12:    PackageCache: .......................... C:\WINDOWS\Installer\566eb2.msi 13:    Vendor: ................................ Microsoft Corporation 14:    *Version: .............................. 5.1.2510.0 

Although it is possible to supply the three keys on the command line to locate the corresponding Win32_Product instance, you will note that the IdentifyingNumber property key is not really easy to type from a command line (GUID number). For the script user facility, the code requests only the Name and the Version property key of the package. By using a WQL query, the script locates the corresponding Windows Installer application (lines 423 through 426 for an install, lines 467 through 470 for an uninstall, and lines 511 through 514 for an upgrade). For these three operations, the script logic is exactly the same in each case. Based on the supplied command-line parameters, the corresponding method with its set of parameters is invoked.

Since WMI is event driven, it is, of course, possible to monitor a package installation with the use of an appropriate WQL event query. Since this provider is not implemented as an event provider, the WQL event query requires the use of the WITHIN statement. The principle to detect the installation of a software product is quite easy, since it consists of tracking down the creation of the Win32_Product instances. For example, the WQL query to use would be as follows:

 Select * From __InstanceCreationEvent Within 10 Where TargetInstance ISA 'Win32_Product' 

3.3.10 Resultant Set of Policies (RSOP) providers

Have you ever dreamed of how good it would be to know if a specific Group Policy Object (GPO) is applied in the user or computer environment? Well, with the WMI implementation of the Resultant Set of Policies (RSOP), this is possible. The RSOP is the set of GPOs effectively applied to a particular user, once logged on, or computer, once booted. The rules that determine if a particular GPO will be applied to a specific user or computer environment are complex. Briefly, the rules are determined by:

  • The GPO container location in the Active Directory hierarchy (Local, Site, Domain, or Organizational Unit)

  • The rights granted on the GPO for the object being considered for application of the considered GPO

  • The WMI filter that applies for the GPO in question

  • The order of the GPO at the container level, since one container may contain several GPO definitions or links (the one at the bottom of the list is the one with the highest priority)

As a consequence, the end result of the GPO application can vary widely. To discover the GPO that is applied or could be applied (simulation) to a particular object, the Windows XP and Windows Server 2003 Operating Systems contain two WMI providers that calculate the RSOP (see Table 3.23). Next, two additional providers expose complementary information about the GPO itself. They are not directly related to RSOP providers, but we will see that they can be useful in an RSOP context as well.

Table 3.23: The RSOP Providers

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

Resultant Set Of Policies Providers

Rsop Planning Mode Provider

Root/RSOP

X

X

X

Rsop Logging Mode Provider

Root/RSOP

X

X

X

PolicSOM provider

Root/Policy

X

X

X

X

X

PolicStatus provider

Root/Policy

X

X

X

The two RSOP providers are located in the Root\RSOP namespace and are implemented as method providers. The two providers enabling complementary information about the GPO are located in the Root\Policy namespace. We will come back to these two providers later while examining the next script sample.

Before examining any methods or classes available, it is interesting to note that under Windows Server 2003, WMI is utilized at two different levels for the GPO.

  • First, a WQL query can be used to filter the GPO appliance. Under Windows 2000, the only way to filter GPO is to create specific rights on the GPO Active Directory object. Based on the granted rights or the group memberships, the GPO is applied to a considered object. Although this way of filtering GPO is still available in Windows Server 2003, it is also possible to filter the GPO by creating a WQL query, called a WMI filter. WMI filters are nothing other than WQL data queries used to verify if there are items in the system matching the specified query. If the query result is positive, the GPO will be applied on the computer or user in question. Obviously, the knowledge of WQL is quite useful in creating these WMI filters. Figure 3.9 shows a WMI filter example for the Default Domain Controller Policy.

    click to expand
    Figure 3.9: A WMI filter created for the Default Domain Controller Policy.

    In Figure 3.9, we see that the WQL data query searches for systems that have the Windows SNMP service installed. With such a query, only the systems that have the SNMP service installed will have the Default Domain Controller Policy applied. You will note the particular syntax, which combines the WMI namespace and WQL data query separated by a semicolumn. This syntax is not WQL specific but is just the way the information is stored in the GPO infrastructure.

  • Second, WMI can be used to calculate the RSOP. Out of the box, Windows Server 2003 and Windows XP offer an MMC snap-in to analyze the RSOP. This MMC snap-in is called the "Resultant Set of Policies" snap-in. Basically this snap-in uses the two WMI providers presented in Table 3.23. In parallel to this MMC snap-in included in Windows Server 2003, Microsoft is currently developing another MMC snap-in to centrally manage the Group Policies. This MMC is called Group Policies Management Console (GPMC) and offers interesting functionalities to manage policies from one single interface despite the fact that GPOs are coming from different Sites, Domains or Forests. GPMC also makes use of the RSOP WMI providers to calculate the Resultant Set Of Policies. Beyond these functionalities, GPMC also implements an object model to manage the GPO from scripts. However, this scriptable object model has no relationship with WMI. At writing time, GPMC is still under development, therefore, more information is available through the Microsoft beta program (although GPMC is supposed to be widely available when Windows Server 2003 is released). With the help of these RSOP providers, and based on the GPO structure, we will see how we can develop a script to retrieve the GPO information and how to determine if some specific GPOs are applied in a specific environment.

It is important to understand that the RSOP providers can be used in two modes, as follows:

  • The Planning mode: Supported by the RSOP Planning mode provider, this mode simulates a snapshot of the policy data that could be present on a computer or user environment by using data from Active Directory. This provider supports one single class called the RsopPlanningModeProvider class. This class consists of two methods, as shown in Table 3.24. The RsopCreateSession method creates a simulated snapshot of the policy data from a particular container (Site, Domain, or Organizational Unit) for a particular user or computer. For the simulation, it is also possible to specify a group membership and a WMI filter for the considered user or computer. The RSOP MMC snap-in, mentioned before, comes with a wizard to collect the various parameters. Behind the scene, the snap-in uses the RsopCreateSession method to produce a Planning mode RSOP result. Of course, we can develop a script to produce an RSOP simulated result, but the script will simply duplicate the functionality provided by the MMC snap-in. Although technically feasible, from a management perspective, writing such a script will not provide any added value compared with the MMC snap-in.

    Table 3.24: The RSOP Classes and Their Methods

    Name

    Type

    Comments

    RsopPlanningModeProvider

    • RsopCreateSession

    Static Method

    Takes a snapshot of actual policy data for display by the RSoP UI.

    • RsopDeleteSession

    Static Method

    Deletes the snapshot of policy data made by RsopCreateSession when the data is no longer required by the RSoP UI.

    • RsopEnumerateUsers

    Static Method

    Returns the list of users whose policy data is available in logging mode.

    RsopPlanningModeProvider

    • RsopCreateSession

    Static Method

    Generates planning mode policy data.

    • RsopDeleteSession

    Static Method

    Deletes planning mode policy data.

  • The Logging mode: Supported by the RSOP Logging mode provider, this mode takes a snapshot of the policy data that is present on a computer or user environment. This provider supports a single class called the RsopLoggingModeProvider class. This class consists of three methods, as shown in Table 3.24. The RsopCreateSession method takes a snapshot of the policy data, which allows any application to display the RSOP data before the system overwrites or deletes it during a refresh of the policy. This mode is the most interesting one from a scripting perspective.

To understand how to work with the RSOP data, it is important to know how it is stored. We saw that the two classes for the Logging and Planning mode are available from the Root\RSOP namespace. To examine Logging mode RSOP data in a Windows XP or Windows Server 2003 computer, we must look at another specific namespace. Here we must make a clear distinction between two types of Logging mode RSOP data, as follows:

  • The RSOP data as is once the user is logged on or when the computer is booted. In such a case, the RSOP data is available from some precreated WMI namespaces in the CIM repository. The first namespace available is the Root\RSOP\Computer namespace, which exposes information about the GPOs applied on the computer. Other namespaces available include the Root\RSOP\User\<SID> namespace, which exposes information about the GPOs applied to users who logged on to the computer system. As you can see, the namespace uses the SID of the user in its name! The Root\RSOP\User\<SID> namespace is created only during the user profile creation. If the namespace is deleted, it will not be recreated until the user profile is recreated, which means that the user profile must be deleted to recreate this namespace. However, once the namespace is created, the namespace is accordingly updated at logon time to reflect the GPOs applied on the user profile. Note that when the user profile is deleted, the RSOP namespace corresponding to the deleted user profile is also deleted. Figure 3.10 shows an example of the namespaces available.


    Figure 3.10: The RSOP subnamespaces.

  • The RSOP data that will be applied during the next policy refresh, which does not necessarily represent the applied GPO after boot or logon. The resulting RSOP data, as it will look after the next refresh, can be created with the RsopCreateSession method. The RSOP information will be stored in a dedicated namespace especially created for that purpose. To create the RSOP data for a user, it is important that the selected user has already logged on to the system. This implies that a namespace, Root\RSOP\User\<SID>, already exists. In such a case, the CreateSession method of the RsopLoggingModeProvider class can be invoked. Basically, when you execute the MMC RSOP snap-in in Logging mode, the snap-in invokes the CreateSession method of the RsopLoggingModeProvider class. The requested information will be available from this dedicated namespace. Figure 3.11 shows an example of the namespaces available.


    Figure 3.11: The RSOP subnamespaces created during a CreateSession method invocation.

Compared with Figure 3.10, a new namespace, called NS1COCCE73_BF05_41C9_935F_C12435CF9196, is created. The subnamespaces of this namespace contain the requested information for each environment (Computer and User).

In both cases, these namespaces contain a collection of classes that represents the set of GPOs that are applied or will be applied during the next refresh cycle. Requesting instances of these classes show if a particular GPO is, or will be, effectively applied in the specified environment. The RSOP classes available are summarized in Table 3.25.

Table 3.25: The RSOP WMI Classes

Name

Comments

Group Policy Core Classes

  • RSOP_ExtensionEventSource

Dynamic

Represents client-side extensions' event log message sources.

  • RSOP_ExtensionEventSourceLink

Dynamic

Represents the association between a client-side extension's event log message source and the extension's status.

  • RSOP_ExtensionStatus

Dynamic

Provides information about the overall status a client-side extension's processing of policy.

  • RSOP_GPO

Dynamic

Provides information about a GPO.

  • RSOP_Session

Dynamic

Represents an RSoP session. There can be only one instance of this class per namespace.

  • RSOP_SOM

Dynamic

Represents a scope of management (SOM) which can be a site, domain, organizational unit, or local scope.

  • RSOP_GPLink

Association

Represents the links from a site, domain, organizational unit, or local scope, to one or more GPOs.

Policy Setting Template Classes

  • RSOP_PolicySetting

Dynamic

The class from which client-side extensions' policy objects are inherited. An instance of this class corresponds to a specific policy setting.

  • RSOP_PolicySettingStatus

Dynamic

Provides a link to an event in the event log that corresponds to an error that occurred while applying a specific policy setting.

  • RSOP_PolicySettingLink

Association

Represents the association between a policy setting and the setting's status.

Registry Policy Classes

  • RSOP_AdministrativeTemplateFile

Dynamic

Represents an administrative template (.adm) file.

  • RSOP_RegistryPolicySetting

Dynamic

Represents the policy object for registry or administrative template extension.

Application Management Policy Classes

  • RSOP_ApplicationManagementCategory

Dynamic

Represents the list of programs in the Add or Remove Programs Control Panel utility.

  • RSOP_ApplicationManagementPolicySetting

Dynamic

Represents the policy data for application management extension.

Folder Redirection and Script Policy Classes

  • RSOP_FolderRedirectionPolicySetting

Dynamic

Provides information about a folder-redirection extension.

  • RSOP_ScriptCmd

Dynamic

Represents a script command and its parameters.

  • RSOP_ScriptPolicySetting

Dynamic

Represents a script setting.

Security Policy Classes (Only available in the Computer RSOP namespace)

  • RSOP_AuditPolicy

Dynamic

Represents the security setting for a local group policy that relates to the auditing of an event type. Events can include, among others, system events and account management events.

  • RSOP_File

Dynamic

Represents a security policy setting that defines the access permissions and audit settings for a securable file system object.

  • RSOP_RegistryKey

Dynamic

Represents a security policy setting that defines the access permissions and audit settings for a particular registry key.

  • RSOP_RegistryValue

Dynamic

Represents specific security-related registry values.

  • RSOP_RestrictedGroup

Dynamic

Represents a security policy setting that defines the members of a restricted (security-sensitive) group.

  • RSOP_SecurityEventLogSettingBoolean

Dynamic

Represents a security policy setting that determines whether or not guests can access the system, application and security event logs.

  • RSOP_SecurityEventLogSettingNumeric

Dynamic

Represents a security policy setting that determines numeric properties related to the system, application and security event logs. Properties include the number of days to retain entries and maximum log size.

  • RSOP_SecuritySettingBoolean

Dynamic

Represents the Boolean security setting for an account policy. Account policies include password ides and account lockout ides.

  • RSOP_SecuritySettingNumeric

Dynamic

Represents the numeric security setting for an account policy. Account policies include password policies, account lockout policies, and Kerberos-related policies.

  • RSOP_SecuritySettings

Dynamic

Abstract class from which other RSoP security classes derive. Instances of this class are not logged. RSOP_SecuritySettings derives from the RSOP_PolicySetting class.

  • RSOP_SecurtySettinString

Dynamic

Represents the string security setting for an account policy.

  • RSOP_SystemService

Dynamic

Represents the security policy setting that defines the start-up mode and access permissions for a particular system service.

  • RSOP_UserPrivilegeRight

Dynamic

Represents the security setting for a local group policy that relates to the assignment of a particular user privilege.

IEAK Policy Classes

  • RSOP_IEAdministrativeTemplateFile

Dynamic

Represents the abstraction for an administrative template (.adm) file for Microsoft Internet Explorer.

  • RSOP_IEAKPolicySetting

Dynamic

Represents the policy data for general settings related to management and customization of Internet Explorer.

  • RSOP_IEAuthenticodeCertificate

Dynamic

Represents the details of customized settings for Internet Explorer that designate software publishers and credentials agencies as trustworthy.

  • RSOP_IEConnectionDialUpCredentials

Dynamic

Represents the settings used by the RasDial function when establishing a dial-up (remote access) connection to the Internet using Internet Explorer.

  • RSOP_IEConnectionDialUpSettings

Dynamic

Contains the details of a phone-book entry for connecting to the Internet; corresponds to the RASENTRY structure.

  • RSOP_IEConnectionSettings

Dynamic

Represents the details of an Internet connection made using Internet Explorer, including details related to auto-configuration.

  • RSOP_IEConnectionWinINetSettings

Dynamic

Represents the settings used by the RasDial function to establish a remote access connection to the Internet using the Microsoft Win32 Internet (Winlnet) application programming interface (API).

  • RSOP_IEFavoriteItem

Dynamic

Represents an item or folder in a user's Internet Explorer Favorites list.

  • RSOP_IEFavoriteOrLinkItem

Dynamic

Parent class from which Internet Explorer Favorites, Favorite folders, and Link toolbar items (Links) are inherited.

  • RSOP_IELinkItem

Dynamic

Represents an Internet Explorer Links bar item (a Link).

  • RSOP_IEPrivacySetting

Dynamic

Represents the privacy settings imported for the Internet security zone.

  • RSOP_IEProgramSetting

Dynamic

Contains details about the imported programs to use for Internet Explorer.

  • RSOP_IEProxySetting

Dynamic

Represents the details of a proxy server connection for Internet Explorer.

  • RSOP_IERegistryPolicySetting

Dynamic

Represents the abstraction for registry extension policy data for Intemet Explorer.

  • RSOP_IESecurityContentRatings

Dynamic

Represents customized settings or attributes related to security content ratings that should be used with Internet Explorer.

  • RSOP_IESecurityZoneSettings

Dynamic

Represents customized settings or attributes to use with Internet Explorer for a particular security zone.

  • RSOP_IEToolbarButton

Dynamic

Represents the toolbar button object for Internet Explorer.

  • RSOP_IEConnectionDialUpCredentialsLink

Association

Represents the association between an Internet Explorer Administration Kit (IEAK) policy setting and the dial-up credentials for a given Internet Explorer Internet connection.

  • RSOP_IEConnectionDalUpSettingsLink

Association

Represents the association between an IEAK policy setting and its imported dial-up settings for a specific connection of Internet Explorer to the Internet.

  • RSOP_IEConnectionSettingsLink

Association

Represents the association between an IEAK policy setting and the policy's Internet connection settings.

  • RSOP_IEConnectionWinINetSettingsLink

Association

Represents the association between an IEAK policy setting and WinInet connection settings for a remote access connection to the Internet

  • RSOP_IEFavoriteItemlink

Association

Represents the association between an IEAK policy setting and an item or folder in a user's Internet Explorer Favorites list.

  • RSOP_IEImportedProgramSettings

Association

Represents the association between an IEAK policy setting and its imported program settings for Internet Explorer.

  • RSOP_IELinkItemLink

Association

Represents the association between an IEAK policy setting and an item in a user's Internet Explorer Links bar.

  • RSOP_IEToolbarButtonLink

Association

Represents the association between an IEAK policy setting and a custom Internet Explorer toolbar button.

Access Method Classes

  • RsopLoggingModeProvider

Dynamic

Contains methods that the RSoP UI calls to take a snapshot of actual policy data in the logging mode.

  • RsopPlanningModeProvider

Dynamic

Contains methods that the RSoP UI calls to create resultant policy data in a what-if (planning mode) scenario.

Note that the Security Policy classes are only available from the Root\RSOP\Computer namespace. The easiest way to verify whether a particular GPO is applied to a User or a Computer is to check if we have instances of the RSOP_PolicySetting class or one of its child classes (see Figure 3.12). This is due to the fact that an instance of the RSOP_PolicySetting class corresponds to a specific GPO setting.


Figure 3.12: The RSOP_PolicySetting superclass.

Since some of these classes are associated with other classes that represent the specific settings of the GPO, by using the WMI associations in place it is possible to retrieve any type of information related to the applied GPO. For example, the RSOP_IEAKPolicySetting, which represents the GPO for the general settings related to management and customization of Internet Explorer, is associated with the collection of classes shown in Figure 3.13.

click to expand
Figure 3.13: The RSOP_IEAKPolicySetting associated classes.

Now let's see how we script with the RSOP providers and the RSOP classes. The following scripts (Samples 3.18 through 3.24) retrieve the RSOP instances from a chosen RSOP class. If one or more instances of the RSOP_PolicySetting (or one of its child classes) are available, the script will display the GPO information available from the RSOP data. If the given class does not have any instance, it means that the selected GPO class is not applied for that particular environment. The following script sample supports these command-line parameters:

 C:\>WMIRSOP.wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIRSOP.wsf /GPOClass:value [/UserRSOP:value] [/UserRSOPOnly[+|-]]                    [/ComputerRSOPOnly[+|-]] [/GPOFullInfo[+|-]] [/NewRSOPSession[+|-]]                    [/Machine:value] [/User:value] [/Password:value] Options: GPOClass         : WMI class name of the GPO to retrieve from RSOP. UserRSOP         : Specifies User RSOP data to retrieve. UserRSOPOnly     : Retrieve applied User GPO only. ComputerRSOPOnly : Retrieve applied Computer GPO only. GPOFullInfo      : Display all GPO information. NewRSOPSession   : Retrieve GPO information from a new RSOP session in logging mode. Machine          : Determine the WMI system to connect to. (default=LocalHost) User             : Determine the UserID to perform the remote connection. (default=none) Password         : Determine the password to perform the remote connection. (default=none) Examples:       WMIRSOP.Wsf /GPOClass:RSOP_SystemService /UserRSOP:Alain.Lissoir                   /SIDResolutionDC:MyDC.LissWare.Net       WMIRSOP.Wsf /GPOClass:RSOP_SystemService /UserRSOP:Alain.Lissoir /GPOFullInfo+                   /SIDResolutionDC:MyDC.LissWare.Net       WMIRSOP.Wsf /GPOClass:RSOP_IEAKPolicySetting /UserRSOP:Alain.Lissoir /UserRSOPOnly+                   /SIDResolutionDC:MyDC.LissWare.Net       WMIRSOP.Wsf /GPOClass:RSOP_IEAKPolicySetting /UserRSOP:Alain.Lissoir /UserRSOPOnly+                   /GPOFullInfo+ /SIDResolutionDC:MyDC.LissWare.Net       WMIRSOP.Wsf /GPOClass:RSOP_SystemService /ComputerRSOPOnly+                   /SIDResolutionDC:MyDC.LissWare.Net       WMIRSOP.Wsf /GPOClass:RSOP_SystemService /ComputerRSOPOnly+ /GPOFullInfo+                   /SIDResolutionDC:MyDC.LissWare.Net       WMIRSOP.Wsf /GPOClass:RSOP_SystemService /NewRSOPSession+ /UserRSOP:Alain.Lissoir                   /SIDResolutionDC:MyDC.LissWare.Net       WMIRSOP.Wsf /GPOClass:RSOP_SystemService /NewRSOPSession+ /UserRSOP:Alain.Lissoir                   /GPOFullInfo+ /SIDResolutionDC:MyDC.LissWare.Net       WMIRSOP.Wsf /GPOClass:RSOP_IEAKPolicySetting /NewRSOPSession+ /UserRSOP:Alain.Lissoir                   /UserRSOPOnly+ /SIDResolutionDC:MyDC.LissWare.Net       WMIRSOP.Wsf /GPOClass:RSOP_IEAKPolicySetting /NewRSOPSession+ /UserRSOP:Alain.Lissoir                   /UserRSOPOnly+ /GPOFullInfo+ /SIDResolutionDC:MyDC.LissWare.Net       WMIRSOP.Wsf /GPOClass:RSOP_SystemService /NewRSOPSession+ /ComputerRSOPOnly+                   /SIDResolutionDC:MyDC.LissWare.Net       WMIRSOP.Wsf /GPOClass:RSOP_SystemService /NewRSOPSession+ /ComputerRSOPOnly+ /GPOFullInfo+                   /SIDResolutionDC:MyDC.LissWare.Net 

Sample 3.18: Retrieving RSOP information from an applied GPO (Part I)

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  40:    </runtime>  41:  42:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\GetSIDFromUserIDFunction.vbs" />  43:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\GetUserIDFromSIDFunction.vbs" />  44:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\ReplaceStringFunction.vbs" />  45:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" />  46:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertiesFunction.vbs" />  47:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  48:  49:    <object prog  reference="true"/>  50:    <object prog  />  51:  52:    <script language="VBscript">  53:    <![CDATA[  ..:  57:    Const cComputerName = "LocalHost"  58:    Const cWMIRSOPNameSpace = "Root\RSOP"  59:    Const cWMIPolicyNameSpace = "Root\Policy"  60:    Const cWMIRSOPUserNameSpace = "Root\RSOP\User"  61:    Const cWMIRSOPComputerNameSpace = "Root\RSOP\Computer"  62:    Const cWMIADNameSpace = "Root\Directory\LDAP"  63:    Const cWMIRSOPLoggingModeClass = "RsopLoggingModeProvider"  64:  65:    ' Diagnostic mode provider flags  66:    Const cFLAG_NO_USER = &h00000001                ' Don't get any user data  67:    Const cFLAG_NO_COMPUTER = &h00000002            ' Don't get any machine data  68:    Const cFLAG_FORCE_CREATENAMESPACE = &h00000004  ' Recreate the namespace for this snapshot.  ..: 101:    ' -------------------------------------------------------------------------------- 102:    ' Parse the command line parameters 103:    If WScript.Arguments.Named.Count = 0 Then 104:       WScript.Arguments.ShowUsage() 105:       WScript.Quit 106:    End If ...: 149:    strComputerName = WScript.Arguments.Named("Machine") 150:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 151: 152:    strSIDResolutionDC = WScript.Arguments.Named("SIDResolutionDC") 153:    If Len(strSIDResolutionDC) = 0 Then strSIDResolutionDC = strComputerName 154: 155:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 156:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 157: 158:    ' Connect to Root\RSOP namespace to invoke RSOP Query available or create new one. 159:    Set objWMIRSOPServices = objWMILocator.ConnectServer(strComputerName, _ 160:                                                         cWMIRSOPNameSpace, _ 161:                                                         strUserID, _ 162:                                                         strPassword) ...: 165:    ' Connect to Root\Policy namespace to gather more information about SOM 166:    Set objWMIPolicyServices = objWMILocator.ConnectServer(strComputerName, _ 167:                                                           cWMIPolicyNameSpace, _ 168:                                                           strUserID, _ 169:                                                           strPassword) ...: 172:    Set objWMIRSOPClass = objWMIRSOPServices.Get (cWMIRSOPLoggingModeClass) ...: 175:    ' Verify the correct User RSOP namespaces ------------------------------------------------- 176:    If boolComputerRSOPOnly = False Then 177:       strUserSIDRSOP = GetSIDFromUserID (strUserRSOP, _ 178:                                          strSIDResolutionDC, _ 179:                                          strUserID, _ 180:                                          strPassword) 181:       If CheckIfRSOPLoggingModeData (objWMIRSOPClass, strUserSIDRSOP) = False Then 182:          WScript.Echo "Requested RSOP data for '" & strUserRSOP & _ 183:                       "' user is not available." 184: 185:          objWMIRSOPClass.RsopEnumerateUsers arrayUserSID, intRC ...: 188:          If intRC = 0 Then 189:             WScript.Echo vbCRLF & "Only the following users are " & _ 190:                          "available for RSOP Logging mode:" & vbCRLF 191:             For Each strUserSID In arrayUserSID 192:                 WScript.Echo " " & GetUserIDFromSID (strUserSID, _ 193:                                                      strSIDResolutionDC, _ 194:                                                      strUserID, _ 195:                                                      strPassword) & _ 196:                                                      " -> " & strUserSID 197:             Next 198:          End If 199: 200:       WScript.Quit 201:       End If 202:    End If 203: ...: ...: ...: 

end example

If a GPO is created to enforce the automatic startup of the SNMP Windows service, as shown in Figure 3.14, and if the script is started with the following command line, the obtained output would be as follows:

  1:   C:\>WMIRSOP.Wsf /GPOClass:RSOP_SystemService /UserRSOP:Alain.Lissoir                                                                 /SIDResolutionDC:MyDC.LissWare.Net  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   - GPO for Brussels Site (RSOP_SystemService) -----------------------------------------------  6:     creationTime: .......................... 01-01-2000  7:     ErrorCode: ............................. 0  8:     GPOID: ................................. CN={A252ACD2-2F93-44B5-ACBF-7948EC5B7080},  9:                                                    CN=Policies,CN=System,DC=LissWare,DC=Net 10:     id: .................................... {244AD6A8-5315-43ED-9810-E6C55FA15127} 11:     name: .................................. 12:     *precedence: ........................... 2 13:     SDDLString: ............................ D:AR(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA) 14:                                                  (A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY) 15:                                                  (A;;CCLCSWLOCRRC;;;IU)S: 16:                                                  (AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD) 17:     *Service: .............................. SNMP 18:     SOMID: ................................. 2 19:     StartupMode: ........................... 2 20:     Status: ................................ 0 21: 22:   - Default Domain Controllers Policy (RSOP_SystemService) ----------------------------------- 23:     creationTime: .......................... 01-01-2000 24:     ErrorCode: ............................. 0 25:     GPOID: ................................. CN={6AC1786C-016F-11D2-945F-00C04fB984F9}, 26:                                                   CN=Policies,CN=System,DC=LissWare,DC=Net 27:     id: .................................... {83884976-3D07-4983-83A8-D115ADF7C777} 28:     name: .................................. 29:     *precedence: ........................... 1 30:     SDDLString: ............................ D:AR(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA) 31:                                                 (A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY) 32:                                                 (A;;CCLCSWLOCRRC;;;IU) 33:                                                 S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD) 34:     *Service: .............................. SNMP 35:     SOMID: ................................. 4 36:     StartupMode: ........................... 2 37:     Status: ................................ 1 38: 39:   The 'RSOP_SystemService' GPO class does not exist in the User RSOP data. 

click to expand
Figure 3.14: A GPO to enforce the automatic startup of the SNMP Windows service at the organizational unit level.

Several remarks must be made about this output. First, we note that two GPOs are listed (from lines 5 and 22) instead of one. Actually, Figure 3.14 only shows the GPO settings of the "Default Domain Controllers Policy," but, in reality, a second policy exists at the Brussels site level, as shown in Figure 3.15.

click to expand
Figure 3.15: A GPO to enforce the automatic startup of the SNMP Windows service at the site level.

Next, we see that the GPO applied at the site level has a precedence of 2 (line 12), while the same GPO applied at the OU level has a precedence of 1. This means that the GPO at the organizational unit (OU) level (highest priority) overwrites the one at the site level (lowest priority). Keep in mind that the last applied GPO is the winner. With this in mind, it makes sense, since the GPO application order is the Local GPO first, the Site GPO next, the Domain GPO, and finally the OU GPO.

Next, we see that the StartupMode property (lines 19 and 36) has a value of 2, which means an automatic service startup (2=Automatic, 3=Manual, and 4=Disabled) for this particular policy. This property is defined at the level of the RSOP_SystemService class (look at the WMI origin definition of the property in the CIM repository).

Based on the GPO application order, we know that only the GPO at the OU level is applied. This information is seen by looking at the Status property. The GPO at the site level has a status of 0 (line 20), while the GPO at the OU level has a status of 1 (line 37). By looking at the CIM origin definition of the Status property, we know that this property is defined at the level of the RSOP_SecuritySettings class. The Status property can take several values, as summarized in Table 3.26.

Table 3.26: The Status Property of the RSOP_SecuritySettings Class

Value

Comments

0

The system did not attempt to configure the setting.

1

The system successfully applied the policy setting for the specific item.

3

The system attempted to configure a specific policy setting but the configuration was not successful.

4

The system attempted to configure the child of a specific policy setting, but the configuration was not successful. Note that this value is valid only for configuration of file system or registry ACLs.

Based on Table 3.26, we see that the Status property reflects the GPO application, since the only GPO with a status of 1 (successfully applied) is the one at the OU level.

It is interesting to note that the RSOP_SystemService class is not available from the User environment. This makes sense, since this GPO is a Computer GPO only (line 39).

Now, if we delete the GPO SNMP Windows service setting at the OU level, the only remaining GPO is the one at the site level. Once the GPO has been refreshed, the same script execution will show the following output:

  1:   C:\>WMIRSOP.Wsf /GPOClass:RSOP_SystemService /UserRSOP:Alain.Lissoir                                                                 /SIDResolutionDC:MyDC.LissWare.Net  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   - GPO for Brussels Site (RSOP_SystemService) -----------------------------------------------  6:     creationTime: .......................... 01-01-2000  7:     ErrorCode: ............................. 0  8:     GPOID: ................................. CN={A252ACD2-2F93-44B5-ACBF-7948EC5B7080},  9:                                             CN=Policies,CN=System,DC=LissWare,DC=Net 10:     id: .................................... {0F317256-2812-48AB-B3F5-B4C49943BF54} 11:     name: .................................. 12:     *precedence: ........................... 1 13:     SDDLString: ............................ D:AR(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA) 14:                                             (A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY) 15:                                             (A;;CCLCSWLOCRRC;;;IU) 16:                                             S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD) 17:     *Service: .............................. SNMP 18:     SOMID: ................................. 2 19:     StartupMode: ........................... 2 20:     Status: ................................ 1 21: 22:   The 'RSOP_SystemService' GPO class does not exist in the User RSOP data. 

We clearly see that the status of the GPO at the site level has changed from 0 to 1 (line 20) and that the precedence has changed from 2 to 1 (line 12).

There are many other properties available from the RSOP classes, and each of these will vary with the GPO. The purpose of this book is not to reproduce the information contained in the Microsoft SDK. Fortunately, the Microsoft SDK gives all the required information about these classes and their properties, but note that the WMI RSOP information is not available from the WMI SDK section. You must look in the "Group Policy Reference" of the "Policies and Profiles" section, in the "Setup and System Administration" general section. During the script sample discussion, we will review some of the characteristics of these classes.

Samples 3.18 through 3.24 contain the full script working with the RSOP Logging mode provider. As with the previous script samples, it starts with the command-line definition (skipped lines 13 through 40) and parsing (lines 101 through 153). However, the WMI connection is a bit unsual, since the script must deal with several namespaces (lines 155 through 241).

The WMI connection is first established with the Root\RSOP namespace. This allows access to the various methods of the RsopLogging-ModeProvider class (lines 155 through 162). Next, a second WMI connection is established with the WMI Root\Policy namespace (lines 165 through 169). This namespace exposes classes that contain some relevant information about the Scope of Management (SOM), which will be discussed later. Next, the script retrieves an instance of the RsopLoggingModeProvider class (line 172). It is interesting to note that an instance of the class must be created, since the exposed methods are static methods (Static qualifier).

Once the RsopLoggingModeProvider class instance is retrieved, the script verifies that the user name given on the command line with the /UserRSOP switch has a corresponding Root\RSOP\<SID> namespace (lines 175 through 202). To perform this verification, the script first retrieves the SID of the given user with the GetSIDFromUserID() function (lines 177 through 180). The GetSIDFromUserID() and the GetSIDFromUserID() functions were developed when examining the Win32_UserAccount class (see Sample 2.67, "Retrieving the SID from the UserID," and Sample 2.68, "Retrieving the UserID from the SID"). Because these functions can establish a WMI connection to another system to perform the UserID to SID and SID to UserID resolution, the script accepts the /SIDResolutionDC switch to select the DC to use. If this switch is not given, the /Machine switch value is used, which is the accessed system for the RSOP information.

Once the SID is known, the script invokes the CheckIfRSOPLoggingModeData() function to check if the Root\RSOP\<SID> namespace exists. This function is based on the RsopEnumerateUsers method of the RsopLoggingModeProvider class (Table 3.24). We will examine this function in Sample 3.24. If the given user has no corresponding Root\RSOP\<SID> namespace, the script retrieves the list of namespaces available with the RsopEnumerateUsers method (line 185) and displays these namespaces with their corresponding user names (lines 189 through 197).

However, if a Root\RSOP\<SID> namespace corresponds to the given user, the script continues its execution (Sample 3.19). The next step creates a new RSOP session if the switch /NewRSOPSession+ is given on the command line.

Sample 3.19: Retrieving RSOP information from an applied GPO (Part II)

start example

 ...: ...: ...: 203: 204:    ' Build the correct RSOP namespaces ------------------------------------------------------- 205:    If boolNewRSOPSession Then 206:       If boolUserRSOPOnly = True And boolComputerRSOPOnly = False Then 207:          intFlags = cFLAG_FORCE_CREATENAMESPACE Or cFLAG_NO_COMPUTER 208:       End If 209:       If boolUserRSOPOnly = False And boolComputerRSOPOnly = True Then 210:          intFlags = cFLAG_FORCE_CREATENAMESPACE Or cFLAG_NO_USER 211:       End If 212:       If boolUserRSOPOnly = False And _ 213:          boolComputerRSOPOnly = False Then 214:          intFlags = cFLAG_FORCE_CREATENAMESPACE 215:       End If 216: 217:       WScript.Echo "Creating new RSOP Logging mode session ..." 218: 219:       objWMIRSOPClass.RsopCreateSession intFlags, _ 220:                                         strUserSIDRSOP, _ 221:                                         strTempNameSpace, _ 222:                                         intRC, _ 223:                                         intExtendedInfo ...: 226:       If intRC = 0 Then 227:          WScript.Echo "New RSOP Logging mode session created." & vbCRLF 228: 229:          strWMIRSOPUserNameSpace = strTempNameSpace & "\User" 230:          strWMIRSOPComputerNameSpace = strTempNameSpace & "\Computer" 231:       Else 232:          WScript.Echo "Unable to create a new RSOP Logging mode session. " & _ 233:                       "(0x" & Hex(IntRC) & ")." 234:          WScript.Quit 235:       End If 236:    Else 237:       strWMIRSOPUserNameSpace = cWMIRSOPUserNameSpace & "\" & strUserSIDRSOP 238:       ReplaceString strWMIRSOPUserNameSpace, "-", "_" 239: 240:       strWMIRSOPComputerNameSpace = cWMIRSOPComputerNameSpace 241:    End If 242: ...: ...: ...: 

end example

In this case, based on the presence of the /ComputerRSOPOnly+ and the /UserRSOPOnly+ switches, the script will determine the flags to use for the RsopCreateSession method invocation. Table 3.27 summarizes the various flag values. By default, if none of these switches is given on the command line, the script will request both User and Computer RSOP information.

Table 3.27: The Logging Mode and Planning Mode Flag Values

Name

Value

Description

Loggin mode provider flags

FLAG_NO_USER

0x1

Don't get any user data

FLAG_NO_COMPUTER

0x2

Don't get any machine data

FLAG_FORCE_CREATENAMESPACE

0x4

Delete and recreate the namespace for this snapshot.

Planning mode provider flags

FLAG_NO_GPO_FILTER

0x80000000

GPOs are not filtered, implies FLAG_NO_CSE_INVOKE

FLAG_NO_CSE_INVOKE

0x40000000

Only GP processing done for planning mode

FLAG_ASSUME_SLOW_LINK

0x20000000

Planning mode RSoP assumes slow link

FLAG_LOOPBACK_MERGE

0x10000000

Planning mode RSoP assumes merge loop back

FLAG_LOOPBACK_REPLACE

0x8000000

Planning mode RSoP assumes replace loop back

FLAG_ASSUME_USER_WQLFILTER_TRUE

0x4000000

Planning mode RSoP assumes all comp filters to be true

FLAG_ASSUME_COMP_WQLFILTER_TRUE

0x2000000

Planning mode RSoP assumes all user filters to be true

Error codes

RSOP_USER_ACCESS_DENIED

0x1

User accessing the RSoP provider doesn't have access to user data.

RSOP_COMPUTER_ACCESS_DENIED

0x2

User accessing the RSoP provider doesn't have access to computer data.

RSOP_TEMPNAMESPACE_EXISTS

0x4

This user is an interactive nonadmin user, the temp snapshot namespace already exists, and the FLAG FORCE CREATENAMESPACE was not passed in.

When creating a new RSOP session, it is possible to select the RSOP information for only the user or for only the computer environment. The flag combination determines the RSOP data requested (lines 206 through 215). Because a new RSOP session creates a temporary namespace (see Figure 3.11), the temporary namespace name is returned in one of the method parameters (line 221). If the method invocation is successful (line 226), the temporary namespaces for the User (line 229) and the Computer RSOP data are initialized (line 230).

If the /NewRSOPSession+ switch is not supplied on the command line, the script initializes the namespace names in order to work with the RSOP data available in the Root\RSOP\Computer and Root\RSOP\User\<SID> namespaces (lines 237 through 240). Note the replacement of the dash (-), which exists in the SID by an underscore (_) (line 238). This character replacement must be done, because WMI uses the SID of the user with underscores instead of dashes to name the namespace.

Once completed, the script is ready to connect to the required RSOP namespaces to examine the User and/or the Computer RSOP data in Logging mode from the current session or from a new session, since the namespace names are initialized accordingly (Sample 3.20).

Sample 3.20: Retrieving RSOP information from an applied GPO (Part III)

start example

 ...: ...: ...: 242: 243:    ' Get the RSOP Computer data -------------------------------------------------------------- 244:    If boolUserRSOPOnly = False Then 245:       ' Connect to RSOP computer namespace 246:       Set objWMIRSOPComputerServices = objWMILocator.ConnectServer(strComputerName, _ 247:                                                                strWMIRSOPComputerNameSpace, _ 248:                                                                strUserID, _ 249:                                                                strPassword) ...: 252:       Set objWMIRSOPInstances = objWMIRSOPComputerServices.InstancesOf (strWMIGPOClass) ...: 255:       If objWMIRSOPInstances.Count Then 256:          If Err.Number Then 257:             WScript.Echo "The '" & strWMIGPOClass & "' GPO class does not " & _ 258:                          "exist in the computer RSOP data." & vbCRLF 259:             Err.Clear 260:          Else 261:             DisplayRSOPInstances objWMIPolicyServices, _ 262:                                  objWMIRSOPComputerServices, _ 263:                                  objWMIRSOPInstances, _ 264:                                  boolGPOFullInfo 265:          End If 266:       Else 267:          WScript.Echo "No computer RSOP data the '" & strWMIGPOClass & _ 268:                          "' GPO class." & vbCRLF 269:       End If ...: 274:    End If 275: ...: ...: ...: 

end example

To examine the RSOP Computer information, the principle is quite simple. First, the script connects to the corresponding namespace (lines 246 through 249). Next, it requests all instances available from the RSOP class given on the command line (line 252). If there is at least one instance available (line 255), it means that a GPO exists for this class. Next, the related information is displayed (lines 261 through 264) via the DisplayRSOPInstances() function. This function will be examined in Sample 3.23.

To retrieve the RSOP User information, the principle is exactly the same as the RSOP Computer information. Only the namespace is different (Sample 3.21).

Sample 3.21: Retrieving RSOP information from an applied GPO (Part IV)

start example

 ...: ...: ...: 275: 276:    ' Get the RSOP User data ------------------------------------------------------------------ 277:    If boolComputerRSOPOnly = False Then 278:       ' Connect to RSOP user namespace 279:       Set objWMIRSOPUserServices = objWMILocator.ConnectServer(strComputerName, _ 280:                                                                strWMIRSOPUserNameSpace, _ 281:                                                                strUserID, _ 282:                                                                strPassword) ...: 285:       Set objWMIRSOPInstances = objWMIRSOPUserServices.InstancesOf (strWMIGPOClass) ...: 288:       If objWMIRSOPInstances.Count Then 289:          If Err.Number Then 290:             WScript.Echo "The '" & strWMIGPOClass & "' GPO class does not " & _ 291:                          "exist in the User RSOP data." & vbCRLF 292:             Err.Clear 293:          Else 294:             DisplayRSOPInstances objWMIPolicyServices, _ 295:                                  objWMIRSOPUserServices, _ 296:                                  objWMIRSOPInstances, _ 297:                                  boolGPOFullInfo 298:          End If 299:       Else 300:          WScript.Echo "No user RSOP data for the '" & strWMIGPOClass & _ 301:                       "' GPO class." & vbCRLF 302:       End If 303: 304:       Set objWMIRSOPInstances = Nothing 305: 306:       Set objWMIRSOPUserServices = Nothing 307:    End If 308: ...: ...: 

end example

Before completion, if a new RSOP session was created, the script deletes the temporary namespace to ensure that the CIM repository is cleaned up (Sample 3.22). The RsopDeleteSession method of the RsopLoggingModeProvider class will delete the temporary namespace (line 311).

Sample 3.22: Retrieving RSOP information from an applied GPO (Part V)

start example

 ...: ...: ...: 308: 309:    ' Delete new session RSOP namespace ------------------------------------------------------- 310:    If boolNewRSOPSession Then 311:       objWMIRSOPClass.RsopDeleteSession strTempNameSpace, _ 312:                                         intRC ...: 315:       If intRC = 0 Then 316:          WScript.Echo "New RSOP Logging mode session deleted." 317:       Else 318:          WScript.Echo "Unable to delete the new RSOP " & _ 319:                       "Logging mode session. (0x" & Hex(IntRC) & ")." 320:       End If 321:    End If 322: ...: ...: ...: 

end example

For each RSOP data (Computer and User), the DisplayRSOPInstances() is invoked (Sample 3.23). To display the RSOP information, the script uses an enumeration technique (lines 345 through 462), since the RSOP instances are retrieved as a collection of instances.

Sample 3.23: Retrieving RSOP information from an applied GPO (Part VI)

start example

 ...: ...: ...: 329: 330:    ' ----------------------------------------------------------------------------------------- 331:    Function DisplayRSOPInstances (objWMIPolicyServices, _ 332:                                   objWMIRSOPServices, _ 333:                                   objWMIRSOPInstances, _ 334:                                   boolGPOFullInfo) ...: 345:        For Each objWMIRSOPInstance In objWMIRSOPInstances 346:            Set objWMIGPOInstance = objWMIRSOPServices.Get ("RSOP_GPO.id='" & _ 347:                                                            objWMIRSOPInstance.GPOID & "'") ...: 350:            WScript.Echo "- " & objWMIGPOInstance.Name & _ 351:                         " (" & objWMIRSOPInstance.Path_.Class & ") " & _ 352:                         String (60, "-") 353: 354:            Set objWMIPropertySet = objWMIRSOPInstance.Properties_ 355:            For Each objWMIProperty In objWMIPropertySet 356:                DisplayFormattedProperty objWMIRSOPInstance, _ 357:                                         " " & objWMIProperty.Name, _ 358:                                         objWMIProperty.Name, _ 359:                                         Null 360:            Next ...: 363:            Set objWMIAssocInstances = objWMIRSOPServices.ExecQuery _ 364:                                                 ("Associators of {" & _ 365:                                                 objWMIRSOPInstance.Path_.RelPath & "}") 366: 367:            For Each objWMIAssocInstance In objWMIAssocInstances 368:                WScript.Echo vbCRLF & " - " & objWMIAssocInstance.Path_.Class & _ 369:                             " " & String (60, "-") 370:                Set objWMIPropertySet = objWMIAssocInstance.Properties_ 371:                For Each objWMIProperty In objWMIPropertySet 372:                    DisplayFormattedProperty objWMIAssocInstance, _ 373:                                             "    " & objWMIProperty.Name, _ 374:                                             objWMIProperty.Name, _ 375:                                             Null 376:                Next ...: 378:            Next ...: 382:            If boolGPOFullInfo Then 383:               WScript.Echo vbCRLF & " - Complementary GPO information (" & _ 384:                            objWMIGPOInstance.Path_.Class & ") " & String (60, "-") 385: 386:               Set objWMIPropertySet = objWMIGPOInstance.Properties_ 387:               For Each objWMIProperty In objWMIPropertySet 388:                   Select Case objWMIProperty.Name 389:                          Case "securityDescriptor" 390: 391:                          Case Else 392:                               DisplayFormattedProperty objWMIGPOInstance, _ 393:                                                        "    " & objWMIProperty.Name, _ 394:                                                        objWMIProperty.Name, _ 395:                                                        Null 396:                   End Select 397:               Next ...: 400:               If Len (objWMIGPOInstance.filterId) Then 401:                  Set objWMIFilterInstance=objWMIPolicyServices.Get(objWMIGPOInstance.filterId) ...: 403:                  WScript.Echo vbCRLF & " - GPO Filter (" & _ 404:                               objWMIFilterInstance.Path_.Class & ") " & String (60, "-") 405:                  Set objWMIPropertySet = objWMIFilterInstance.Properties_ 406:                  For Each objWMIProperty In objWMIPropertySet 407:                      If objWMIProperty.CIMType = wbemCimtypeObject Then 408:                         For Each varElement In objWMIProperty.Value 409:                             DisplayFormattedProperties varElement, 6 410:                         Next 411:                      Else 412:                         DisplayFormattedProperty objWMIFilterInstance, _ 413:                                                  "      " & objWMIProperty.Name, _ 414:                                                  objWMIProperty.Name, _ 415:                                                  Null 416:                      End If 417:                  Next ...: 419:               End If 420: 421:               Set objWMIAssocInstances = objWMIRSOPServices.ExecQuery _ 422:                                                    ("Associators of {" & _ 423:                                                    objWMIGPOInstance.Path_.RelPath & "}") 424: 425:               For Each objWMIAssocInstance In objWMIAssocInstances 426:                   WScript.Echo vbCRLF & " - GPO Scope of Domain (" & _ 427:                                 objWMIAssocInstance.Path_.Class & ") " & String (60, "-") 428:                   Set objWMIPropertySet = objWMIAssocInstance.Properties_ 429:                   For Each objWMIProperty In objWMIPropertySet 430:                       DisplayFormattedProperty objWMIAssocInstance, _ 431:                                                "    " & objWMIProperty.Name, _ 432:                                                objWMIProperty.Name, _ 433:                                                Null 434:                   Next ...: 436:               Next ...: 440:               Set objWMIAssocInstances = objWMIRSOPServices.ExecQuery _ 441:                                                    ("References of {" & _ 442:                                                    objWMIGPOInstance.Path_.RelPath & "}") 443: 444:               For Each objWMIAssocInstance In objWMIAssocInstances 445:                   WScript.Echo vbCRLF & " - GPO link (" & _ 446:                                objWMIAssocInstance.Path_.Class & ") " & String (60, "-") 447:                   Set objWMIPropertySet = objWMIAssocInstance.Properties_ 448:                   For Each objWMIProperty In objWMIPropertySet 449:                       DisplayFormattedProperty objWMIAssocInstance, _ 450:                                                "    " & objWMIProperty.Name, _ 451:                                                objWMIProperty.Name, _ 452:                                                Null 453:                   Next ...: 455:               Next ...: 458:            End If 459:            WScript.Echo ...: 462:        Next ...: 466:    End Function 467: ...: ...: ...: 

end example

For each RSOP instance, a different level of information is retrieved:

  • Information about the RSOP instance (lines 346 through 360): First, an instance of the RSOP_GPO class is retrieved. This class includes information about a GPO. To retrieve this information, the script uses the GPOID property of the RSOP class (lines 346 and 347). This instance is useful to display the GPO container name (line 350). If more details about the GPO are requested by the /GPOFullInfo+ switch, this instance will be used again. Next, the script displays the properties of the RSOP instance coming from the class given on the command line (lines 354 through 360).

  • Information about the RSOP associated instances (lines 363 through 378): If there are some instances associated with the RSOP instance, the WQL query executed in this portion of the code (lines 363 through 365) will return a collection of instances. Next, the returned collection is enumerated (lines 367 through 378) and the information displayed (lines 370 through 376). For example, if instances of the RSOP_IEAKPolicySetting class are examined, it is likely that some associated instances will be available (see Figure 3.13).

Next, the script enters in a code portion, which is only executed if the /GPOFullInfo+ switch is specified (lines 382 through 458). In such a case, the output obtained would be as follows:

  1:   C:\>WMIRSOP.Wsf /GPOClass:RSOP_SystemService /UserRSOP:Alain.Lissoir /GPOFullInfo+  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   - GPO for Brussels Site (RSOP_SystemService) -----------------------------------------------  6:     creationTime: .......................... 01-01-2000  7:     ErrorCode: ............................. 0  8:     GPOID: ................................. CN={A252ACD2-2F93-44B5-ACBF-7948EC5B7080},  9:                                              CN=Policies,CN=System,DC=LissWare,DC=Net 10:     id: .................................... {6562C1CD-B998-44C4-85A8-3BB1F780E1D9} 11:     name: .................................. 12:     *precedence: ........................... 1 13:     SDDLString: ............................ D:AR(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA) 14:                                              (A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY) 15:                                              (A;;CCLCSWLOCRRC;;;IU) 16:                                              cS:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD) 17:     *Service: .............................. SNMP 18:     SOMID: ................................. 2 19:     StartupMode: ........................... 2 20:     Status: ................................ 1 21: 22:     - Complementary GPO information (RSOP_GPO) ----------------------------------------------- 23:       accessDenied: ........................ FALSE 24:       enabled: ............................. TRUE 25:       fileSystemPath: ...................... \\LissWare.Net\SysVol\ 26:                                              LissWare.Net\Policies\ 27:                                              {A252ACD2-2F93-44B5-ACBF-7948EC5B7080}\Machine 28:       filterAllowed: ....................... TRUE 29:       filterId: ............................ MSFT_SomFilter.ID= 30:                                              "{C455EC3F-A9BF-4EA0-B224-571CA683B11C}", 31:                                              Domain="LissWare.Net" 32:       guidName: ............................ {A252ACD2-2F93-44B5-ACBF-7948EC5B7080} 33:       *id: ................................. CN={A252ACD2-2F93-44B5-ACBF-7948EC5B7080}, 34:                                              CN=Policies,CN=System,DC=LissWare,DC=Net 35:       name: ................................ GPO for Brussels Site 36:       version: ............................. 65537 37: 38:       - GPO Filter (MSFT_SomFilter) ---------------------------------------------------------- 39:         Author: ............................ Alain.Lissoir 40:         ChangeDate: ........................ 25-01-2002 14:46:38 41:         CreationDate: ...................... 01-01-2002 14:55:53 42:         Description: ....................... Only applied SNMP 43:         *Domain: ........................... LissWare.Net 44:         *ID: ............................... {C455EC3F-A9BF-4EA0-B224-571CA683B11C} 45:         Name: .............................. Only for SNMP machines 46: 47:         - MSFT_Rule -------------------------------------------------------------------------- 48:         Query: ............................. Select * From Win32_Service Where Name="SNMP" 49:         QueryLanguage: ..................... WQL 50:         TargetNameSpace: ................... Root\cimv2 51: 52:     - GPO Scope of Domain (RSOP_SOM) --------------------------------------------------------- 53:       blocked: ............................. FALSE 54:       blocking: ............................ FALSE 55:       *id: ................................. CN=Brussels,CN=Sites,CN=Configuration, 56:                                              DC=LissWare,DC=Net 57:       *reason: ............................. 1 58:       SOMOrder: ............................ 2 59:       type: ................................ 2 60: 61:     - GPO link (RSOP_GPLink) ----------------------------------------------------------------- 62:       appliedOrder: ........................ 2 63:       enabled: ............................. TRUE 64:       *GPO: ................................ RSOP_GPO.id= 65:                                              "CN={A252ACD2-2F93-44B5-ACBF-7948EC5B7080}, 66:                                              CN=Policies,CN=System,DC=LissWare,DC=Net" 67:       linkOrder: ........................... 2 68:       noOverride: .......................... FALSE 69:       *SOM: ................................ RSOP_SOM.,reason=1 71:       *somOrder: ........................... 1 72: 73:   The 'RSOP_SystemService' GPO class does not exist in the User RSOP data. 

The supplementary information displayed by the presence of the /GPOFullInfo+ switch starts at line 22.

This portion of the script (Sample 3.23, lines 378 through 452) also retrieves different levels of information about the GPO:

  • Information about the RSOP_GPO instance (lines 383 through 397): This instance is retrieved earlier in the script code (lines 346 and 347), but its related information is only displayed if the /GPOFullInfo+ switch is specified (lines 386 through 397).

  • Information about the list of rules, expressed as WMI queries, which are evaluated on the target machine (lines 400 through 419): This portion of the code makes use of the RSOP_GPO instance previously retrieved (lines 346 and 347) and the namespace Root\Policy connection established at lines 166 through 169. It exploits the FilterID property displayed in the output sample at lines 29 through 31, which contains a WMI path of a GPO filter corresponding to an instance of the MSFT_SomFilter class:

     MSFT_SomFilter.,Domain="LissWare.Net" 

    The classes available in the Root\Policy namespace are listed in Table 3.28.

    Table 3.28: The Root\Policy Classes

    Name

    Type

    Comments

    MSFT_SomFilterStatus

    Dynamic

    Represents client-side extensions' event log message sources.

    MSFT_Rule

    Dynamic

    Represents the association between a dient-side extension's event log message source and the extension's status.

    MSFT_SomFilter

    Dynamic

    Provides information about the overall status of a client-side extension's processing of policy.

    Once the instance of the WMI path is retrieved (line 401), the script displays its properties (lines 405 through 417). The output is available from line 38 through 45. It is important to note that the Rules property of the MSFT_SomFilter class contains an array of objects (embedded objects). The purpose of the syntax evaluation at line 407 is to determine if an object is contained in the property. If the test is positive, the array containing objects is enumerated (lines 408 through 410), and the properties of each object are displayed with the help of the DisplayFormattedProperties() function (line 409). The output is available from line 47 through 50. You will recognize the WMI filter displayed in Figure 3.9.

    For completeness, since WMI filters are stored in Active Directory, it is possible to retrieve the filters by executing a WQL query in the Root\directory\LDAP namespace:

     Select * From ads_msWMI_Som Where DS_cn="{C455EC3F-A9BF-4EA0-B224-571CA683B11C}" 

    The WMI filters use the ID property of the MSFT_SomFilter WMI class as the CN of the Active Directory object. The Active Directory object representing a WMI filter uses an msWMI-Som Active Directory class. In section 3.6, we see in more depth how to work with the Active Directory providers.

  • Information about the Scope of Management (SOM) (lines 421 through 436): Because we have an instance of the RSOP_GPO class (lines 346 and 347), it is interesting to exploit a new association not yet mentioned. This association is shown in Figure 3.16.

    click to expand
    Figure 3.16: The RSOP_GPO association.

    With this association, we retrieve instances of the RSOP_SOM class. This class contains information about the SOM, which could be Local, a Site, a Domain, or an OU. This information is displayed in the output example from line 52 through 59. Some relevant information is available from this class:

    • The "blocked" state (line 53), which is a flag that indicates whether this SOM is blocked by a SOM lower in the hierarchy of Sites, Domains, and OUs.

    • The "blocking" state (line 54), which is a flag that indicates whether this SOM blocks inheritance of policy from other SOMs higher in the hierarchy.

    • The SOM (line 55) itself, which is the Brussels site in this case.

  • Information about the GPO link (lines 440 through 455): Since we have an association in place, an association class is used with its references (lines 440 through 442). In this case, the class is the RSOP_GPLink class. By retrieving the instances available from this class, we can get some interesting information about the GPO (lines 61 through 71 in the output sample). For example, we can see if the GPO is enabled (line 63) and its override state (line 68).

The last piece of code of this script sample simply contains the CheckIfRSOPLoggingModeData() function, which was used earlier (line 181). The script code makes use of this routine to test if the Root\RSOP\User\<SID> namespace is available for the User name given on the command line. This function compares (line 482) the SID of the user (passed as a parameter) with the list of SIDs available from the RSOP User namespaces (line 474). If there is a match, it means that the namespace exists.

Sample 3.24: Retrieving RSOP information from an applied GPO (Part VII)

start example

 ...: ...: ...: 467: 468:    ' ----------------------------------------------------------------------------------------- 469:    Function CheckIfRSOPLoggingModeData (objWMIRSOPClass, strUserSIDRSOP) ...: 477:        CheckIfRSOPLoggingModeData = False 478: 479:        objWMIRSOPClass.RsopEnumerateUsers arrayUserSID, intRC ...: 482:        If intRC Then 483:           Exit Function 484:        End If 485: 486:        For Each strUserSID In arrayUserSID 487:            If strUserSID = strUserSIDRSOP Then 488:              CheckIfRSOPLoggingModeData = True 489:              Exit Function 490:            End If 491:        Next 492: 493:    End Function 494: 495:    ]]> 496:    </script> 497:  </job> 498:</package> 

end example

We now have an understanding of how an RSOP is represented by WMI. To monitor the appearance or the deletion of a specific GPO during a refresh cycle, WQL event queries can be submitted in the appropriate namespaces (i.e., Root\RSOP\Computer). If a Windows service GPO is applied to a computer, the following WQL event query should be used:

 Select * From __InstanceCreationEvent Within 5 Where TargetInstance ISA 'RSOP_SystemService' 

If the same GPO is removed, the following WQL event query should be used:

 Select * From __InstanceDeletionEvent Within 5 Where TargetInstance ISA 'RSOP_SystemService' 

Note the presence of the WITHIN statement, since the RSOP providers are not implemented as event providers.

If we reuse Sample 6.17 ("A generic script for asynchronous event notification") presented in the appendix, we can easily track the GPO creation and deletion. For example, for a GPO deletion, we will have:

  1:   C:\>GenericEventAsyncConsumer.wsf "Select * From __InstanceDeletionEvent Within 5                  Where TargetInstance ISA 'RSOP_SystemService'" /NameSpace:Root\RSOP\Computer  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   Waiting for events...  6:  7:   BEGIN - OnObjectReady.  8:   Sunday, 03 February, 2002 at 13:01:42: '__InstanceDeletionEvent' has been triggered.  9:     SECURITY_DESCRIPTOR (wbemCimtypeUint8) = (null) 10:     TargetInstance (wbemCimtypeObject) 11:       creationTime (wbemCimtypeDatetime) = (null) 12:       ErrorCode (wbemCimtypeUint32) = 0 13:       GPOID (wbemCimtypeString) = CN={6AC1786C-016F-11D2-945F-00C04fB984F9}, 14:                                                    CN=Policies,CN=System,DC=LissWare,DC=Net 15:       id (wbemCimtypeString) = {25127460-F569-4D2C-95FB-69D47F0294B5} 16:       name (wbemCimtypeString) = 17:       *precedence (wbemCimtypeUint32) = 1 18:       SDDLString (wbemCimtypeString) = D:AR(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA) 19:                                        (A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY) 20:                                        (A;;CCLCSWLOCRRC;;;IU) 21:                                        S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD) 22:       *Service (wbemCimtypeString) = SNMP 23:       SOMID (wbemCimtypeString) = 4 24:       StartupMode (wbemCimtypeUint32) = 2 25:       Status (wbemCimtypeUint32) = 1 26:     TIME_CREATED (wbemCimtypeUint64) = 03-02-2002 12:01:42 (20020203120142.177488+060) 27: 28:   END - OnObjectReady. 

In this sample output, we recognize the properties of the RSOP_SystemService class discussed in this section. Of course, as with any WQL query, it can be generalized with the use of a parent class to capture any GPO type creation and deletion. This means we have a mechanism to monitor any updates on any systems.

Since the GPO mechanism is quite complex, there is no better way than to play with the script to understand the underlying mechanisms. This is key for a good understanding of this technology.

3.3.11 The System Restore provider

To undo harmful changes to a computer, Windows XP includes a feature called System Restore. System Restore returns the Operating System to an earlier situation (called a restore point) without causing the loss of all recent work. Any changes that System Restore makes are completely reversible. Windows XP automatically creates restore points (called system checkpoints), but it is also possible to create your own restore points. This is useful if you are about to make a major change to your system, such as installing a new program or changing your registry. The System Restore wizard, located in the System Tools folder of the Start Menu, allows you to perform System Restore operations (see Figure 3.17).

click to expand
Figure 3.17: The System Restore wizard.

When a restore point is created, System Restore archives the states of a core set of system and application files with a full snapshot of the registry and some dynamic system files. To function properly, System Restore requires a minimum of 200 MB of free disk space on the system drive. If the free disk space falls below 50 MB on any drive, System Restore switches to standby mode and stops creating restore points. In such a case, all restore points are deleted. If you recover 200 MB of free disk space, the System Restore resumes and continues to create restore points. The set of files that is monitored or excluded by System Restore is specified in an XML file called FILELIST.XML and located in the %windir%\System32\Restore folder. When a user is not actively using the Windows XP system, System Restore compresses the registry and any file copies made.

Although restore points can be created with the System Restore wizard (see Figure 3.17), it is also possible to perform the exact same operation from a script by using the SystemRestore class supported by the System Restore WMI provider. Only available under Windows XP and registered under the Root\Default namespace, the System Restore WMI provider is implemented as an instance and method provider (see Table 3.29).

Table 3.29: The SystemRestore Providers Capabilities

Provider Name

Provider Namespace

Class Provider

Instance Provider

Method Provider

Property Provider

Event Provider

Event Consumer Provider

Support Get

Support Put

Support Enumeration

Support Delete

Windows Server 2003

Windows XP

Windows 2000 Server

Windows 2000 Professional

Windows NT 4.0

System Restore Provider

System Restore Provider

Root/Default

X

X

X

X

X

X

The System Restore provider supports two WMI classes (see Table 3.30).

Table 3.30: The SystemRestore Providers Classes

Name

Type

Comments

SystemRestore

Dynamic

Provides methods for disabling and enabling monitoring, listing available restore points, and initiating a restore on the local system.

SystemRestoreConfig

Dynamic

Provides properties for controlling the frequency of scheduled restore point creation and the amount of disk space consumed on each drive.

The class supporting System Restore operations from a script is the SystemRestore class. Basically, this class supports five methods implementing the five typical System Restore operations. As with the wizard, it is possible to create new restore points, to enable or disable the System Restore monitoring for all disks or per disk, get the last System Restore status, and restore a specific restore point with this class. To configure the various intervals and the percentage of disk space used by System Restore, the SystemRestoreConfig class must be used. The logic making use of these classes is implemented in Samples 3.25 through 3.31. The code is written in Jscript and is called WMISystemRestore.Wsf. This sample exposes a set of command-line parameters corresponding to methods exposed by the SystemRestore class and properties exposed by the SystemRestoreConfig class.

Sample 3.25: Exploiting the System Restore features from script (Part I)

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  37:    </runtime>  38:  39:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodeSystemRestoreFunction.vbs" />  40:  41:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" />  42:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  43:  44:    <object progobjWMILocator" reference="true''/>  45:    <object progobjWMIDateTime" />  46:  47:    <script language="Jscript">  48:    <![CDATA[  49:    var cComputerName = "LocalHost";  50:    var cWMINameSpace = "Root/Default";  51: ...: 147: 148:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault; 149:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate; 150: 151:    try 152:      { 153:      objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, 154:                                                   strUserID, strPassword); 155:      } 156:    catch (Err) 157:      { 158:      ErrorHandler (Err); 159:      } 160: ...: ...: ...: 

end example

 C:\>WMISystemRestore.wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMISystemRestore.wsf /Action:value [/Volume:value] [/Description:value]                            [/RestoreSequence[+|-]] [/DiskPercentage[+|-]] [/GlobalInterval[+|-]]                            [/LifeInterval[+|-]] [/SessionInterval[+|-]]                            [/Machine:value] [/User:value] [/Password:value] Options: Action          : Specify the operation to perform: [List], [Disable], [Enable],                   [CreateRestorePoint], [LastRestoreStatus], [Restore] and [Update]. Volume          : Specify the System Resstore volume (i.e., C:\ or * for all volumes). Description     : Description for the new restore point. RestoreSequence : Sequence number of the restore point. DiskPercentage  : Maximum amount of disk space on each drive that can be used by System Restore. GlobalInterval  : Absolute time interval at which scheduled system checkpoints are created (hours). LifeInterval    : Time interval for which restore points are preserved (hours). SessionInterval : Time interval at which scheduled system checkpoints are created                   during the session (hours) Machine         : Determine the WMI system to connect to. (default=LocalHost) User            : Determine the UserID to perform the remote connection. (default=none) Password        : Determine the password to perform the remote connection. (default=none) Examples:       WMISystemRestore.wsf /Action:List       WMISystemRestore.wsf /Action:Disable /Volume:D:\       WMISystemRestore.wsf /Action:Enable /Volume:D:\       WMISystemRestore.wsf /Action:Disable /Volume:*       WMISystemRestore.wsf /Action:Enable /Volume:*       WMISystemRestore.wsf /Action:CreateRestorePoint /Description:"My System Restore"       WMISys terries tore.wsf /Action:LastRestoreStatus       WMISystemRestore.wsf /Action: Restore /RestoreSequence : 28 /Volume:C:       WMISystemRestore.wsf /Action:Update /DiskPercentage:12 /GlobalInterval:72                                           /LifeInterval:120 /SessionInterval:120 

As with other script samples, the WMISystemRestore.Wsf script (see Sample 3.25) starts with the command-line parameter definition (skipped lines 13 through 37), the inclusion of some external functions (lines 39 through 45), the command-line parsing (skipped lines 49 through 147), and the WMI connection (lines 148 through 159).

To view the restore points available, Sample 3.26 retrieves all instances of the SystemRestore class (line 166). The scripting technique is quite easy, since it simply consists of an enumeration of all instances (lines 173 through 218) with all their properties (lines 183 through 216).

Sample 3.26: Viewing the System Restore points (Part II)

start example

 ...: ...: ...: 160: 161:    // -- LIST --------------------------------------------------------------------------- 162:    if (boolList == true) 163:      { 164:      try 165:        { 166:        objWMIInstances = objWMIServices.InstancesOf ("SystemRestore") 167:        } 168:      catch (Err) 169:        { 170:        ErrorHandler (Err) 171:        } 172: 173:      enumWMIInstances = new Enumerator (objWMIInstances); 174:      for (;! enumWMIInstances.atEnd(); enumWMIInstances.moveNext()) 175:          { 176:          objWMIInstance = enumWMIInstances.item(); 177: 178:          objWMIDateTime.Value = objWMIInstance.CreationTime; 179:          WScript.Echo ("- " + objWMIInstance.Description + " (" + 180:                        objWMIDateTime.GetVarDate (false) + ")" + 181:                        "-------------------------------------------------------"); 182: 183:          objWMIPropertySet = objWMIInstance.Properties_ 184:          enumWMIPropertySet = new Enumerator (objWMIPropertySet); 185:          for (;! enumWMIPropertySet.atEnd(); enumWMIPropertySet.moveNext()) 186:              { 187:              objWMIProperty = enumWMIPropertySet.item() 188: 189:              switch (objWMIProperty.Name) 190:                     { 191:                     case "RestorePointType": 192:                          DisplayFormattedProperty (objWMIInstance, 193:                                 "  " + objWMIProperty.Name, 194:                                 DecodeRestorePointType (objWMIProperty.Value), 195:                                 null); 196:                          break; 197:                     case "EventType": 198:                          DisplayFormattedProperty (objWMIInstance, 199:                                 "  " + objWMIProperty.Name, 200:                                 DecodeEventType (objWMIProperty.Value), 201:                                 null); 202:                          break; 203:                     case "CreationTime": 204:                          DisplayFormattedProperty (objWMIInstance, 205:                                 "  " + objWMIProperty.Name, 206:                                 objWMIDateTime.GetVarDate (false), 207:                                 null); 208:                          break; 209:                     default: 210:                          DisplayFormattedProperty (objWMIInstance, 211:                                 "  " + objWMIProperty.Name, 212:                                 objWMIProperty.Name, 213:                                 null); 214:                          break; 215:                     } 216:              } 217:          WScript.Echo(); 218:          } 219:      } 220: ...: ...: ...: 

end example

To enable or disable the System Restore disk monitoring, the scripting technique is pretty simple. Sample 3.27 retrieves an instance of the System Restore class (lines 224 and 250). Because these Disable and Enable methods do not relate to a particular dynamic instance, they are defined as static methods (Static qualifier set to true) in the CIM repository. Actually, the logical disk for which the System Restore monitoring must be enabled or disabled must be specified as a parameter of the methods (lines 224 and 250). If a drive letter is specified on the command line (in the form "C:\" or "D:\"), the method will be related to the specified disk (lines 232 and 258). If an asterisk is given on the command line, the method will apply to all disks (lines 226 and 252). In this case, the disk letter will be an empty string when passing the parameter to the method (lines 228 and 254). Interestingly, the disk is not managed via a WMI instance stored in an SWBemObject, which represents the real disk. Instead, it is managed by an instance of the class where parameters specify the disk to manage (lines 228 and 254). This implementation is totally dependent on how the WMI provider and its supported classes are designed.

Sample 3.27: Enabling/disabling disk monitoring (Part III)

start example

 ...: ...: ...: 220: 221:    // -- ENABLE ---- 222:    if (boolEnable == true) 223:       { 224:       objWMIClass = objWMIServices.Get ("SystemRestore") 225: 226:       if (strDevicelD == "*") 227:          { 228:          intRC = objWMIClass.Enable ("", true) 229:          } 230:       else 231:          { 232:          intRC = objWMIClass.Enable (strDeviceID, true) 233:          } 234: 235:       if (intRC) 236:          { 237:          WScript.Echo ("Failed to enable SystemRestore on " + 238:                         strDeviceID + " drive (" + intRC + ")") 239:          } 240:       else 241:          { 242:          WScript.Echo ("SystemRestore on " + strDeviceID + 243:                        " drive successfully enabled.") 244:          } 245:       } 246: 247:    // -- DISABLE --------------------------------------------------------------------------- 248:    if (boolDisable == true) 249:       { 250:       objWMIClass = objWMIServices.Get ("SystemRestore") 251: 252:       if (strDeviceID == "*") 253:          { 254:          intRC = objWMIClass.Disable ("") 255:          } 256:       else 257:          { 258:          intRC = objWMIClass.Disable (strDeviceID) 259:          } 260: 261:       if (intRC) 262:          { 263:          WScript.Echo ("Failed to disable SystemRestore on " + 264:                        strDeviceID + " drive (" + intRC + ")") 265:          } 266:       else 267:          { 268:          WScript.Echo ("SystemRestore on " + strDeviceID + 269:                        " drive successfully disabled.") 270:          } 271:       } 272: ...: ...: ...: 

end example

To create a restore point, the same logic applies as enabling or disabling a disk (see Sample 3.28). An instance of the SystemRestore class is first retrieved (line 276). Next, the CreateRestorePoint method is invoked (lines 278 through 280).

Sample 3.28: Creating a restore point (Part IV)

start example

 ...: ...: ...: 272: 273:    // -- CreateRestorePoint ---------------------------------------------------------------- 274:    if (boolCreateRestorePoint == true) 275:       { 276:       objWMIClass = objWMIServices.Get ("SystemRestore") 277: 278:       intRC = objWMIClass.CreateRestorePoint (strDescription, 279:                                               APPLICATION_INSTALL, 280:                                               BEGIN_SYSTEM_CHANGE) 281: 282:       if (intRC) 283:          { 284:          WScript.Echo ("Failed to create a new system restore point (" + intRC + ")") 285:          } 286:       else 287:          { 288:          WScript.Echo ("System restore point successfully created.") 289:          } 290:       } 291: ...: ...: 

end example

The three parameters passed along the method invocation are as follows:

  • Description: The Description parameter is a string used to identify the restore point.

  • RestorePointType: The RestorePointType is an integer defining the type of restore point. The various values that can be specified with this parameter are summarized in Table 3.31.

    Table 3.31: The RestorePointType Parameter

    Name

    Value

    Comments

    APPLICATION_INSTALL

    0

    An application has been installed.

    APPLICATION_UNINSTALL

    1

    An application has been uninstalled.

    DEVICE_DRIVER_INSTALL

    10

    A device driver has been installed.

    MODIFY_SETTINGS

    12

    An application has had features added or removed.

    CANCELLED_OPERATION

    13

    An application needs to delete the restore point it created. For example, an application would use this flag when a user cancels an installation.

  • EventType: The EventType is an integer defining the type of event for the restore point. The various values that can be specified with this parameter are summarized in Table 3.32.

    Table 3.32: The EventType Parameter

    Name

    Value

    Comments

    BEGIN_NESTED_SYSTEM_CHANGE

    102

    A system change has begun. A subsequent nested call does not create a new restore point. Subsequent calls must use END_NESTED_SYSTEM_CHANGE, not END_SYSTEM_CHANGE.

    BEGIN_SYSTEM_CHANGE

    100

    A system change has begun.

    END_NESTED_SYSTEM_CHANGE

    103

    A system change has ended.

    END_SYSTEM_CHANGE

    101

    A system change has ended.

Getting the last restore status from the script is a very simple operation (see Sample 3.29). The GetLastRestoreStatus method is a static method and is therefore executed from an instance of the SystemRestore class (lines 295 through 297). The last restore status is returned as a result of the method execution.

Sample 3.29: Getting the last restore status (Part V)

start example

 ...: ...: ...: 291: 292:    // -- LastRestoreStatus ----------------------------------------------------------------- 293:    if (boolRestoreStatus == true) 294:       { 295:       objWMIClass = objWMIServices.Get ("SystemRestore") 296: 297:       intRC = objWMIClass.GetLastRestoreStatus () 298: 299:       WScript.Echo ("Last restore status: " + intRC) 300:       } 301: ...: ...: ...: 

end example

To restore a restore point, the coding is no more complicated than getting the last restore status (see Sample 3.30). The Restore static method must still be executed from an instance of SystemRestore class. The only required input parameter to execute the Restore method is the restore point sequence number. The restore point sequence number can be found by executing the WMISystemRestore.Wsf script with the /Action:List command-line parameter. A sample output will look as follows:

  1:   C:\>WMISystemRestore.wsf /Action:List  2:   Microsoft (R) Windows Script Host Version 5.6  3:   Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:   - System Checkpoint (Fri Oct 11 10:33:16 UTC+0200 2002)-------------------------------------  6:     CreationTime: .......................... 11-10-2002 10:33:16  7:     Description: ........................... System Checkpoint  8:     EventType: ............................. BEGIN_SYSTEM_CHANGE  9:     RestorePointType: ...................... APPLICATION_INSTALL 10:     *SequenceNumber: ....................... 45 11: 12:   - Windows Update V4 (Fri Oct 11 21:38:54 UTC+0200 2002)------------------------------------- 13:     CreationTime: .......................... 11-10-2002 21:38:54 14:     Description: ........................... Windows Update V4 15:     EventType: ............................. BEGIN_SYSTEM_CHANGE 16:     RestorePointType: ...................... APPLICATION_INSTALL 17:     *SequenceNumber: ....................... 46 18: 19:   - System Checkpoint (Sun Oct 13 07:50:20 UTC+0200 2002)------------------------------------- 20:     CreationTime: .......................... 13-10-2002 07:50:20 21:     Description: ........................... System Checkpoint 22:     EventType: ............................. BEGIN_SYSTEM_CHANGE 23:     RestorePointType: ...................... APPLICATION_INSTALL 24:     *SequenceNumber: ....................... 47 

Sample 3.30: Restoring a restore point (Part VI)

start example

 ...: ...: ...: 301: 302:    // -- Restore ---------------------------------------------------------------------------- 303:    if (boolCreateRestorePoint == true) 304:       { 305:       objWMIClass = objWMIServices.Get ("SystemRestore") 306: 307:       intRC = objWMIClass.Restore(intSequenceNumber) 308: 309:       if (intRC) 310:          { 311:          WScript.Echo ("Failed to create a new system restore point (" + intRC + ")") 312:          } 313:       else 314:          { 315:          WScript.Echo ("System restore point successfully created.") 316:          } 317:       } 318: ...: ...: ...: 

end example

As we can see, the sequence number is a key property of the SystemRestore instances (lines 10, 17, and 24).

To manage the properties controlling the frequency of the scheduled restore point creation and the amount of disk space consumed on each drive, the SystemRestoreConfig class must be used, as shown in Sample 3.31.

Sample 3.31: Updating the System Restore parameters (Part VII)

start example

 ...: ...: ...: 318: 319:    // -- Update ---------------------------------------------------------------------------- 320:    if (boolUpdate == true) 321:       { 322:       objWMIInstance = objWMIServices.Get ("SystemRestoreConfig.MyKey='SR'"); 323: 324:       if (intDiskPercentage != -1) objWMIInstance.DiskPercent=intDiskPercentage; 325:       if (intGlobalInterval != -1) objWMIInstance.RPGlobalInterval=intGlobalInterval*3600; 326:       if (intLifeInterval != -1) objWMIInstance.RPLifeInterval=intLifeInterval*3600; 327:       if (intSessionInterval != -1) objWMIInstance.RPSessionInterval=intSessionInterval*3600; 328: 329:       try 330:         { 331:         objWMIInstance.Put_ (wbemChangeFlagUpdateOnly | wbemFlagReturnWhenComplete); 332:         } 333:       catch (Err) 334:         { 335:         ErrorHandler (Err); 336:         } 337: 338:       WScript.Echo ("System restore point parameters updated.") 339:       } 340:    ]]> 341:    </script> 342:  </job> 343:</package> 

end example

The only instance available from the SystemRestoreConfig class is the SR instance (line 322). That instance exposes the disk percentage in the Disk-Percent property and the three frequency properties in RPGlobalFrequency, RPLifeInterval, and RPSessionInterval, respectively (lines 324 through 327). The meaning of these properties is summarized in Table 3.33. Note that the script accepts the schedule parameters in hours, while the SystemRestoreConfig class exposes these properties in seconds. That's why the script code multiplies the values by 3,600 during the property assignment (lines 324 through 327).

Table 3.33: The SystemRestoreConfig Properties

Name

Comments

DiskPercent

Maximum amount of disk space on each drive that can be used by System Restore. This value is specified as a percentage of the total drive space. The default value is 12 percent.

RPGlobalInterval

Absolute time interval at which scheduled system checkpoints are created, in seconds. The default value is 86,400 (24 hours).

RPLifeInterval

Time interval for which restore points are preserved, in seconds. When a restore point becomes older than this specified interval, it is deleted. The default age limit is 90 days.

RPSessionInterval

Time interval at which scheduled system checkpoints are created during the session, in seconds. The default value is zero, indicating that the feature is turned off.




Leveraging WMI Scripting
Leveraging WMI Scripting: Using Windows Management Instrumentation to Solve Windows Management Problems (HP Technologies)
ISBN: 1555582990
EAN: 2147483647
Year: 2003
Pages: 82
Authors: Alain Lissoir

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