2.4 Operating System classes


2.4 Operating System classes

2.4.1 COM component classes

Most of the classes examined in the previous samples were related to the hardware. With the COM components category, and the categories that we examine in the next sections, we start to examine classes that are related to the Operating System. The Operating System classes represent operating system—related objects. They describe the various configurations and settings that define a computing environment. Besides the COM component settings, this also includes the boot configuration, the desktop environment settings, the drivers, the security settings, the user settings, and the registry settings. Let's start with the COM component settings first. The classes related to the COM components are shown in Table 2.12.

Table 2.12: The COM Component Classes

Name

Type

Description

Win32_ClassicCOMClass

Dynamic

Represents the properties of a COM component.

Win32_COMApplication

Dynamic

Represents a COM application.

Win32_COMClass

Dynamic

Represents the properties of a Component Object Model (COM) component.

Win32_ComponentCategory

Dynamic

Represents a component category.

Win32_COMSetting

Dynamic

Represents the settings associated with a COM component or COM application.

Win32_DCOMApplication

Dynamic

Represents the properties of a DCOM application.

Win32_DCOMApplicationSetting

Dynamic

Represents the settings of a DCOM application.

Win32_ClassicCOMApplicationClasses

Association

Relates a DCOM application and a COM component grouped under it.

Win32_ClassicCOMClassSettings

Association

Relates a COM dass and the settings used to configure Dynamics of the COM class.

Win32_CIientApplicationSetting

Association

Relates an executable and a DCOM application that contains the DCOM confi guration options for the executable file.

Win32_COMApplicationCIasses

Association

Relates a COM component and the COM application where it resides.

Win32_COMApplicationSettings

Association

Relates a DCOM application and its configuration settings.

Win32_ComClassAutoEmulator

Association

Relates a COM dass and another COM class that it automatically emulates.

Win32_ComClassEmulator

Association

Relates two versions of a COM class.

Win32_DCOMApplicationAccessAllowedSetting

Association

Relates the Win32_DCOMApplication Dynamic and the user SIDs that can access it.

Win32_DCOMApplicationLaunchAllowedSetting

Association

Relates the Win32_DCOMApplication Dynamic and the user SIDs that can launch it.

Win32_ImplementedCategory

Association

Relates a component category and the COM class using its interfaces.

When working with WMI and real-world manageable entities, we always use WMI providers. As we have seen before, the WMI providers are implemented as COM components. In the previous chapter, we created a script retrieving information from instances of the __Win32Provider system class (see Samples 1.1 through 1.3, "Locating WMI provider registration instances with their exposed classes"). We can reuse the logic developed in these scripts to gather the COM information about the WMI providers. This is the purpose of Sample 2.24.

Sample 2.24: Locating the WMI provider registration instances with their COM information

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  14:      <named name="Machine" helpstring="determine the WMI system to connect to.                                 (default=LocalHost)" required="false" type="string"/>  15:      <named name="User" helpstring="determine the UserID to perform the remote connection.                                 (default=none)" required="false" type="string"/>  16:      <named name="Password" helpstring="determine the password to perform the remote                                 connection. (default=none)" required="false" type="string"/>  17:    </runtime>  18:  19:    <script language="VBScript" src="/books/2/679/1/html/2/.\Functions\DisplayFormattedPropertyFunction.vbs" />  20:    <script language="VBScript" src="/books/2/679/1/html/2/.\Functions\TinyErrorHandler.vbs" />  21:  22:    <object prog  reference="true"/>  23:    <object prog  />  24:  25:    <script language="VBscript">  26:    <![CDATA[  ..:  30:    Const cComputerName = "LocalHost"  31:    Const cWMICIMv2NameSpace = "Root\CIMv2"  32:    Const cWMINameSpace = "Root"  33:    Const cWMINamespaceClass = "__NAMESPACE"  34:    Const cWMIClass = "__Win32Provider"  ..:  42:    ' --------------------------------------------------------------------------------  43:    ' Parse the command line parameters  ..:  51:    If Len(strComputerName) = 0 Then strComputerName = cComputerName  52:  53:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault  54:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate  55:  56:    Set objWMICIMv2Services = objWMILocator.ConnectServer(strComputerName, _  57:                                                          cWMICIMv2NameSpace, _  58:                                                          strUserID, _  59:                                                          strPassword)  ..:  62:    DisplayNameSpaces cWMINameSpace, cWMIClass, strUserID, strPassword, strComputerName  63:  64:    ' --------------------------------------------------------------------------------------  65:    Private Function DisplayNameSpaces (ByVal strWMINameSpace, _  66:                                        ByVal strWMIClass, _  67:                                        ByVal strUserID, _  68:                                        ByVal strPassword, _  69:                                        ByVal strComputerName)  ..:  79:        objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault  80:        objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate  81:        Set objWMIServices = objWMILocator.ConnectServer(strComputerName, _  82:                                                         strWMINameSpace, _  83:                                                         strUserID, _  84:                                                         strPassword)  ..:  86:  87:        Set objWMIProviderInstances = objWMIServices.InstancesOf (strWMIClass, _  88:                                                                  wbemQueryFlagShallow)  89:        If Err.Number Then  90:           Err.Clear  91:        Else  92:           WScript.Echo strWMINameSpace  93:           For Each objWMIProviderInstance In objWMIProviderInstances  94:  95:               WScript.Echo "  " & objWMIProviderInstance.Name  96:  97:               Set objCOMSettingInstance = objWMICIMv2Services.Get _  98:                                              ("Win32_ClassicCOMClassSetting.ComponentId='" & _  99:                                              objWMIProviderInstance.CLSID & "'") 100: 101:               Set objWMIPropertySet = objCOMSettingInstance.Properties_ 102:               For Each objWMIProperty In objWMIPropertySet 103:                   DisplayFormattedProperty objCOMSettingInstance, _ 104:                                            "    " & objWMIProperty.Name, _ 105:                                            objWMIProperty.Name, _ 106:                                            Null 107:               Next ...: 112:           Next ...: 114:        End If 115: 116:        Set objWMINSInstances = objWMIServices.InstancesOf (cWMINamespaceClass, _ 117:                                                            wbemQueryFlagShallow) 118:        For Each objWMINSInstance in objWMINSInstances 119:            DisplayNameSpaces strWMINameSpace & "/" & objWMINSInstance.Name, _ 120:                              strWMIClass, strUserID, strPassword, strComputerName 121:        Next ...: 126:    End Function 127: 128:    ]]> 129:    </script> 130:  </job> 131:</package> 

end example

Sample 2.24 is exactly the same as Samples 1.1 through 1.3 until line 93. From line 97 through 99, the script retrieves the COM instance of the examined WMI provider instance by using its class ID (CLSID). The class ID is represented by the ComponentID property in the __Win32Provider class. This property can be used as selection criteria to locate the COM object instance, because the Win32_ClassicCOMClassSettings class uses this property as a key. Once the COM component instance is available, the script shows its properties (lines 101 through 107). Next, the script enumerates the rest of the collection (line 112) and locates the next WMI namespace (lines 116 through 121).

The output from Sample 2.24 is partially represented in the following code segment. The result is interesting, since it shows the file (.DLL or .Exe) implementing the COM component, which is the WMI provider (see lines 16, 25, 45, and 55).

  1:    C:\>LocateProvidersWithCOMInfo.wsf  2:    Microsoft (R) Windows Script Host Version 5.6  3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:    Root  6:    Root/SECURITY  7:    Root/RSOP  8:      Rsop Planning Mode Provider  9:        AppID: ............................... {6EBBFC6C-B721-4D10-9371-5D8E8C76D315} 10:        Caption: ............................. RsopPlanningModeProvider Class 11:        *ComponentId: ........................ {F0FF8EBB-F14D-4369-bd2e-d84fbf6122d6} 12:        Control: ............................. FALSE 13:        Description: ......................... RsopPlanningModeProvider Class 14:        Insertable: .......................... FALSE 15:        JavaClass: ........................... FALSE 16:        LocalServer32: ....................... %SystemRoot%\system32\rsopprov.exe 17:        ProgId: .............................. RSOPPROV.RsopPlanningModeProvider.1 18:        VersionIndependentProgId: ............ RSOPPROV.RsopPlanningModeProvider 19: 20:      Rsop Logging Mode Provider 21:        Caption: ............................. Rsop Logging Mode Provider 22:        *ComponentId: ........................ {B3FF88A4-96EC-4cc1-983F-72BE0EBB368B} 23:        Control: ............................. FALSE 24:        Description: ......................... Rsop Logging Mode Provider 25:        InprocServer32: ...................... J:\WINDOWS\system32\USERENV.dll 26:        Insertable: .......................... FALSE 27:        JavaClass: ........................... FALSE 28:        ThreadingModel: ...................... Both 29: 30:    Root/RSOP/User 31:    Root/RSOP/User/ms_409 32:    Root/RSOP/User/S_1_5_21_2025429265_507921405_1202660629_1112 33:    Root/RSOP/User/S_1_5_21_2025429265_507921405_1202660629_500 34:    Root/RSOP/User/S_1_5_21_2025429265_507921405_1202660629_1140 35:    Root/RSOP/Computer 36:    Root/RSOP/Computer/ms_409 37:    Root/Cli 38:    Root/snmp 39:    Root/snmp/localhost 40:      MS_SNMP_CLASS_PROVIDER 41:        Caption: ............................. Microsoft WBEM SNMP Class Provider 42:        *ComponentId: ........................ {70426720-F78F-11cf-9151-00AA00A4086C} 43:        Control: ............................. FALSE 44:        Description: ......................... Microsoft WBEM SNMP Class Provider 45:        InprocServer32: ...................... J:\WINDOWS\System32\wbem\snmpincl.dll 46:        Insertable: .......................... FALSE 47:        JavaClass: ........................... FALSE 48:        ThreadingModel: ...................... Both 49: 50:      MS_SNMP_ENCAPSULATED_EVENT_PROVIDER 51:        Caption: ............................. Microsoft WBEM SNMP Event Provider 52:        *ComponentId: ........................ {19C813AC-FEE7-11D0-AB22-00C04FD9159E} 53:        Control: ............................. FALSE 54:        Description: ......................... Microsoft WBEM SNMP Event Provider 55:        InprocServer32: ...................... J:\WINDOWS\System32\wbem\snmpincl.dll 56:        Insertable: .......................... FALSE 57:        JavaClass: ........................... FALSE 58:        ThreadingModel: ...................... Both ..: ..: ..: 

You can compare the obtained output for the SNMP class provider (lines 41 through 48) with the registry data shown in Figure 2.7.

click to expand
Figure 2.7: The SNMP class provider COM information from the registry.

The Win32_ClassicCOMClassSetting class relates to the traditional COM object settings. However, by using the Win32_DCOMApplicationSetting class, it is possible to retrieve the settings of a DCOM application. In Understanding WMI Scripting, Chapter 1, when discovering WSH, we talk about a feature called WSH remote. This WSH feature is based on DCOM. If we use the Win32_DCOMApplicationSetting class, it is possible to retrieve the DCOM settings of this application. Sample 2.25 contains the code listing the Win32_DCOMApplicationSetting class settings.

Sample 2.25: Retrieving DCOM application settings

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  14:      <unnamed name="DCOMAppsName" helpstring="the WMI instance name." required="true"                                      type="string" />  15:      <named name="Machine" helpstring="determine the WMI system to connect to.                                      (default=LocalHost)" required="false" type="string"/>  16:      <named name="User" helpstring="determine the UserID to perform the remote connection.                                      (default=none)" required="false" type="string"/>  17:      <named name="Password" helpstring="determine the password to perform the remote                                      connection. (default=none)" required="false" type="string"/>  18:    </runtime>  19:  20:    <script language="VBScript" src="/books/2/679/1/html/2/.\Functions\DecodeDCOMAuthLevelFunction.vbs" />  21:  22:    <script language="VBScript" src="/books/2/679/1/html/2/.\Functions\DisplayFormattedPropertyFunction.vbs" />  23:    <script language="VBScript" src="/books/2/679/1/html/2/.\Functions\TinyErrorHandler.vbs" />  24:  25:    <object prog  reference="true"/>  26:    <object prog  />  27:  28:    <script language="VBscript">  29:    <![CDATA[  ..:  33:    Const cComputerName = "LocalHost"  34:    Const cWMINameSpace = "root/cimv2"  35:    Const cWMIClass = "Win32_DCOMApplicationSetting"  ..:  48:    ' --------------------------------------------------------------------------------  49:    ' Parse the command line parameters  50:    If WScript.Arguments.Unnamed.Count = 0 Then  51:       WScript.Arguments.ShowUsage()  52:       WScript.Quit  53:    Else  54:       strWMIInstance = WScript.Arguments.Unnamed.Item(0)  55:    End If  ..:  66:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault  67:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate  68:  69:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _  70:                                                     strUserID, strPassword)  ..:  73:    Set objWMIInstances = objWMIServices.InstancesOf (cWMIClass)  ..:  76:    For Each objWMIInstance in objWMIInstances  77:        If Ucase (objWMIInstance.Caption) = Ucase(strWMIInstance) Then  78:           Set objWMIPropertySet = objWMIInstance.Properties_  79:           For Each objWMIProperty In objWMIPropertySet  80:               Select Case objWMIProperty.Name  81:                      Case "AuthenticationLevel"  82:                           DisplayFormattedProperty objWMIInstance, _  83:                              objWMIProperty.Name, _  84:                              DCOMAuthLevel (objWMIInstance.AuthenticationLevel), _  85:                                                    Null  86:                      Case Else  87:                           DisplayFormattedProperty objWMIInstance, _  88:                              objWMIProperty.Name, _  89:                              objWMIProperty.Name, _  90:                              Null  91:               End Select  92:           Next  ..:  94:        End If  95:    Next  96:    WScript.Echo  ..: 101:    ]]> 102:    </script> 103:  </job> 104:</package> 

end example

This sample simply lists the properties available from the Win32_DCOMApplicationSetting instance (lines 78 through 92). The instance is retrieved from the name given on the command line (lines 54 and 77). By default, the output obtained with the WSHRemote default settings is:

 C:\>GetDCOMAppsSettings.wsf WSHRemote Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. *AppID: .................................. {6F201542-B482-11D2-A250-00104BD35090} AuthenticationLevel: ..................... Default Caption: ................................. WSHRemote Description: ............................. WSHRemote EnableAtStorageActivation: ............... FALSE UseSurrogate: ............................ FALSE 

If these settings are modified, as shown in Figure 2.8, the output is affected as follows:

 C:\>GetDCOMAppsSettings.wsf WSHRemote Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. *AppID: .................................. {6F201542-B482-11D2-A250-00104BD35090} AuthenticationLevel: ..................... Packet                                            (authentication is performed on ...) Caption: ................................. WSHRemote Description: ............................. WSHRemote EnableAtStorageActivation: ............... TRUE RemoteServerName: ........................ XP-DPEP6400.LissWare.Net RunAsUser: ............................... LISSWARENET\alain.lissoir UseSurrogate: ............................ FALSE 

click to expand
Figure 2.8: The WSHRemote settings modification.

Note that Figure 2.8 does not show the DCOM security settings. Even if these settings are modified, Sample 2.25 does not show the updated security settings. To show these DCOM rights we have to work with the Win32_DCOMApplicationAccessAllowedSetting and Win32_DCOMApplicationLaunchAllowedSetting association classes. These two classes are two association classes linking the Win32_SID class with the Win32_DCOMApplication class (see Figure 2.9).

click to expand
Figure 2.9: The Win32_DCOMApplication class associations.

2.4.2 Desktop information classes

The desktop information class category retrieves information about the user's desktop. This includes the current desktop settings, the environment variables, and the time zone. The classes included in this category are listed in Table 2.13.

Table 2.13: The Desktop Classes

Name

Type

Description

Win32_Desktop

Dynamic

Represents the common characteristics of a user's desktop.

Win32_Environment

Dynamic

Represents an environment or system environment setting on a Windows computer system.

Win32_TimeZone

Dynamic

Represents the time zone information for a Windows system.

Win32_UserDesktop

Association

Relates a user account and desktop settings that are specific to it.

Have you ever wanted to know if the profile of your users has the screen saver activated? Well, by using the Win32_Desktop class, you can determine if this is the case and which screen saver is selected. If we simply reuse Sample 1.5 ("Listing all instances of a class with their properties formatted") developed in the previous chapter, we can list the desktop settings located in every Windows NT profile stored on the system. The output is as follows:

  1:    C:\>GetCollectionOfInstances.wsf Win32_Desktop /MAchine:MyPortable.LissWare.Net  2:    Microsoft (R) Windows Script Host Version 5.6  3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:  6:    BorderWidth: ............................. 1  7:    CoolSwitch: .............................. TRUE  8:    CursorBlinkRate: ......................... 530  9:    DragFullWindows: ......................... TRUE 10:    GridGranularity: ......................... 0 11:    IconSpacing: ............................. 43 12:    IconTitleFaceName: ....................... Tahoma 13:    IconTitleSize: ........................... 8 14:    IconTitleWrap: ........................... TRUE 15:    *Name: ................................... MYPORTABLE\Alain.Lissoir 16:    Pattern: ................................. (None) 17:    ScreenSaverActive: ....................... TRUE 18:    ScreenSaverExecutable: ................... C:\WINNT\System32\ss3dfo.scr 19:    ScreenSaverSecure: ....................... TRUE 20:    ScreenSaverTimeout: ...................... 180 21:    Wallpaper: ............................... C:\WINNT\CompaqFlag.bmp 22:    WallpaperStretched: ...................... FALSE 23:    WallpaperTiled: .......................... FALSE 24: 25:    BorderWidth: ............................. 1 26:    CoolSwitch: .............................. TRUE 27:    CursorBlinkRate: ......................... 530 28:    DragFullWindows: ......................... TRUE 29:    GridGranularity: ......................... 0 30:    IconSpacing: ............................. 43 31:    IconTitleFaceName: ....................... Tahoma 32:    IconTitleSize: ........................... 8 33:    IconTitleWrap: ........................... TRUE 34:    *Name: ................................... MYPORTABLE\Administrator 35:    Pattern: ................................. (None) 36:    ScreenSaverActive: ....................... FALSE 37:    ScreenSaverExecutable: ................... (NONE) 38:    ScreenSaverSecure: ....................... FALSE 39:    ScreenSaverTimeout: ...................... 900 40:    Wallpaper: ............................... C:\WINNT\Compaq.bmp 41:    WallpaperStretched: ...................... FALSE 42:    WallpaperTiled: .......................... FALSE 43: 44:    BorderWidth: ............................. 1 45:    CoolSwitch: .............................. TRUE 46:    CursorBlinkRate: ......................... 530 47:    DragFullWindows: ......................... FALSE 48:    GridGranularity: ......................... 0 49:    IconSpacing: ............................. 43 50:    IconTitleFaceName: ....................... Tahoma 51:    IconTitleSize: ........................... 8 52:    IconTitleWrap: ........................... TRUE 53:    *Name: ................................... .DEFAULT 54:    Pattern: ................................. (None) 55:    ScreenSaverActive: ....................... TRUE 56:    ScreenSaverExecutable: ................... logon.scr 57:    ScreenSaverSecure: ....................... FALSE 58:    ScreenSaverTimeout: ...................... 900 59:    Wallpaper: ............................... C:\WINNT\Compaq.bmp 60:    WallpaperStretched: ...................... FALSE 61:    WallpaperTiled: .......................... FALSE 

As we see, the name property is the key property of the Win32_Desktop class and contains a Windows user account. The Win32_Desktop class is linked with the Win32_UserAccount class via the Win32_UserDesktop asso ciation class (see Figure 2.10).

click to expand
Figure 2.10: The Win32_Desktop class associations.

This link enables an application to retrieve information about the user account associated with a desktop. We revisit the Win32_UserAccount class later in this chapter (section 2.4.15, "User account classes").

In the same way, the Win32_TimeZone retrieves the current Time Zone settings. As before, if we use previous Sample 1.5 ("Listing all instances of a class with their properties formatted"), we get one instance that corresponds to the current time zone settings.

  1:    C:\>GetCollectionOfInstances.wsf Win32_TimeZone  2:    Microsoft (R) Windows Script Host Version 5.6  3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:  6:    Bias: .................................... 60  7:    Caption: ................................. (GMT+01:00) Brussels, Copenhagen, Madrid, Paris  8:    DaylightBias: ............................ -60  9:    DaylightDay: ............................. 5 10:    DaylightDayOfWeek: ....................... 0 11:    DaylightHour: ............................ 2 12:    DaylightMillisecond: ..................... 0 13:    DaylightMinute: .......................... 0 14:    DaylightMonth: ........................... 3 15:    DaylightName: ............................ Romance Daylight Time 16:    DaylightSecond: .......................... 0 17:    DaylightYear: ............................ 0 18:    Description: ............................. (GMT+01:00) Brussels, Copenhagen, Madrid, Paris 19:    StandardBias: ............................ 0 20:    StandardDay: ............................. 5 21:    StandardDayOfWeek: ....................... 0 22:    StandardHour: ............................ 3 23:    StandardMillisecond: ..................... 0 24:    StandardMinute: .......................... 0 25:    StandardMonth: ........................... 10 26:    *StandardName: ........................... Romance Standard Time 27:    StandardSecond: .......................... 0 28:    StandardYear: ............................ 0 

Undoubtedly, the most interesting class in this category is the Win32_ Environment class, which allows the manipulation of the environment variables. This class can be used to create, update, and delete user and system environment variables. Sample 2.26 is a script example that performs all these operations from the command line.

Sample 2.26: Reading, creating, updating, and deleting environment variables (Part I)

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  28:    </runtime>  29:  30:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  31:  32:    <object prog  reference="true"/>  33:    <object prog  reference="true"/>  34:  35:    <script language="VBscript">  36:    <![CDATA[  ..:  40:    Const cComputerName = "LocalHost"  41:    Const cWMINameSpace = "root/cimv2"  42:    Const cWMIClass = "Win32_Environment"  ..:  67:    ' --------------------------------------------------------------------------------  68:    ' Parse the command line parameters         If WScript.Arguments.Named.Count Then  70:       Select Case Ucase(WScript.Arguments.Named("Action"))  71:              Case "LIST"  72:                   boolList = True  73:              Case "CREATE"  74:                   boolCreate = True  75:              Case "UPDATE"  76:                   boolUpdate = True  77:              Case "DELETE"  78:                   boolDelete = True  79:              Case Else  80:                   WScript.Echo "Invalid action type. Only ... are accepted." & vbCRLF  81:                   WScript.Arguments.ShowUsage()  82:                   WScript.Quit  83:       End Select  84:  85:       Select Case Ucase(WScript.Arguments.Named("Env"))  86:              Case "USER"  87:                   boolUserEnv = True  88:              Case "SYSTEM"  89:                   boolUserEnv = False  90:              Case Else  91:                   strUserEnv = WScript.Arguments.Named("Env")  92:                   If Len(strUserEnv) = 0 And Not boolList = True Then  93:                      WScript.Echo "Invalid ... type. Only ... are accepted." & vbCRLF  94:                      WScript.Arguments.ShowUsage()  95:                      WScript.Quit  96:                   End If  97:                   boolUserEnv = True  98:       End Select  99:    End If 100: 101:    If WScript.Arguments.Unnamed.Count = 0 And Not boolList = True Then 102:       WScript.Echo "Environment variable with its value is missing." & vbCRLF 103:       WScript.Arguments.ShowUsage() 104:       WScript.Quit 105:    Else 106:       If Not boolList = True Then 107:          strEnvVar = WScript.Arguments.Unnamed.Item(0) 108:          intEqualPosition = InStr (strEnvVar, "=") 109:          If intEqualPosition Then 110:             strEnvVarValue = Mid (strEnvVar, intEqualPosition + 1) 111:             strEnvVar = Mid (strEnvVar, 1, intEqualPosition - 1) 112:          Else 113:             If Not boolDelete = True Then 114:                WScript.Echo "Invalid environment variable value." & vbCRLF 115:                WScript.Arguments.ShowUsage() 116:                WScript.Quit 117:             End If 118:          End If 119:       End If 120:    End If 121: 122:    boolForce = WScript.Arguments.Named("Force") 123:    If Len(boolForce) = 0 Then boolForce = False 124: 125:    strUserID = WScript.Arguments.Named("User") 126:    If Len(strUserID) = 0 Then strUserID = "" 127: 128:    strPassword = WScript.Arguments.Named("Password") 129:    If Len(strPassword) = 0 Then strPassword = "" 130: 131:    strComputerName = WScript.Arguments.Named("Machine") 132:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 133: 134:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 135:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 136: 137:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 138:                                                     strUserID, strPassword) 139:    If Err.Number Then ErrorHandler (Err) 140: ...: ...: ...: 

end example

Before diving into the code, let's see the available command-line parameters.

 C:\>WMIEnv.Wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Environment variable with its value is missing. Usage: WMIEnv.wsf [EnvVariable] /Env:value /Action:value [/Force[+|-]]                   [/Machine:value] [/User:value] [/Password:value] Options: EnvVariable : The environment variable name with its value. Env         : Specify the environment type: [system] for the system, [user] for the current               user, [Domain\UserAccout] for any other user account. Action      : Specify the operation to perform: [list] or [create] or [update] or [delete]. Force       : Force a creation if the update fails, force an update if the creation fails. 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) Example:       WMIEnv.wsf /Action:List       WMIEnv.wsf MyVariable=MyValue /Env:LISSWARENET\Alain.Lissoir /Action:Create       WMIEnv.wsf MyOtherVariable=MyValue /Env:SYSTEM /Action:Create       WMIEnv.wsf MyOtherVariable /Env:SYSTEM /Action:Delete 

As we can see, the script accepts four action types. Each action corresponds to the Win32_Environment operations supported. Basically, we have a first section to view the environment variables, a second section to create environment variables, a third section to update existing environment variables, and a fourth section to delete environment variables.

As usual, the script starts with the command-line parameters definition (skipped lines 13 through 28) and parsing (lines 69 through 132). The command-line parsing is a bit more complex, because some switches are only required for some specific actions. For instance, when /Action:List switch is used, no other command-line parameter is needed. However, when the /Action:Create switch is used, some more command-line parameters are required. In the case of the /Action:Create switch, the complete command line is as follows:

 C:\WMIEnv MyVariable=MyValue /Action:Create /Env:Alain.Lissoir 

When creating an environment variable, it is mandatory to specify the variable name with its value. Next, it is also necessary to specify the environment type where this new variable must be created (user or system). The parameters are verified from line 70 through 83 for the /Action switch, from line 85 through 98 for the /Env switch, and from line 106 through 119 for the variable name with its value. Once the command-line parameters are parsed and the WMI connection is executed, the corresponding environment variable action is executed accordingly (see Samples 2.27 through 2.30).

Each section of the script corresponds to a particular action. Sample 2.27 shows the code to read the environment variables.

Sample 2.27: Reading environment variables (Part II)

start example

 ...: ...: ...: 140: 141:    ' -- LIST --------------------------------------------------------------------------- 142:    If boolList = True Then 143:       Set objWMIInstances = objWMIServices.InstancesOf (cWMIClass) 144: 145:       For Each objWMIInstance In objWMIInstances 146:           WScript.Echo objWMIInstance.Name 147:           WScript.Echo "  " & objWMIInstance.Name & "=" & objWMIInstance.VariableValue 148:           WScript.Echo "  PROFILE=" & objWMIInstance.UserName 149:           WScript.Echo "  SYSTEM=" & objWMIInstance.SystemVariable 150:       Next 151: 152:       WScript.Echo vbCRLF & "Completed." 153: 154:       Set objWMIInstance = Nothing 155:    End If 156: ...: ...: ...: 

end example

This code segment requests all instances of the Win32_Environment class (line 143). Once the collection is created, the script enumerates the variable name (line 146), its value (line 147), and its related profile and profile type (lines 148 and 149).

The environment variable creation is a bit more complex. The first point to note is that the Win32_Environment class does not expose any method to create an environment variable. The trick to create a new variable is to create a new instance of the Win32_Environment class by using the Put_ method of a spawned SWbemObject. Sample 2.28 shows how this works.

Sample 2.28: Creating environment variables (Part III)

start example

 ...: ...: ...: 156: 157:    ' -- CREATE ------------------------------------------------------------------------- 158:    If boolCreate = True Then 159:       Set objWMIClass = objWMIServices.Get (cWMIClass) 160:       Set objWMIInstance = objWMIClass.SpawnInstance_ 161: 162:       If boolUserEnv = True Then 163:          If Len(strUserEnv) = 0 Then 164:             objWMIInstance.UserName = WshNetwork.UserDomain & "\" & WshNetwork.UserName 165:          Else 166:             objWMIInstance.UserName = strUserEnv 167:          End If 168:          objWMIInstance.SystemVariable = False 169:       Else 170:          objWMIInstance.UserName = "<SYSTEM>" 171:          objWMIInstance.SystemVariable = True 172:       End If 173: 174:       objWMIInstance.Name = strEnvVar 175:       objWMIInstance.VariableValue = strEnvVarValue 176: 177:       If boolForce = True Then 178:          objWMIInstance.Put_ (wbemChangeFlagCreateOrUpdate Or wbemFlagReturnWhenComplete) 179:       Else 180:          objWMIInstance.Put_ (wbemChangeFlagCreateOnly Or wbemFlagReturnWhenComplete) 181:       End If ...: 184:       WScript.Echo "Environment variable '" & strEnvVar & "' created." ...: 187:    End If 188: ...: ...: ...: 

end example

First, the script creates a new instance of the Win32_Environment class (lines 159 and 160). Based on the environment variable type (user or system), the script initializes the required properties (lines 162 through 172). Note that if the /Env switch has a value equal to "User," the script retrieves the name of the user running the script with some WSH objects (line 164). It is important to note that if you execute the script with a remote system, it is mandatory to explicitly specify the remote user name environment, since WSH only retrieves the local user name. Next, the variable name and its value are stored in the new instance (lines 174 and 175). At line 177, the script tests if the switch /Force+ is specified on the command line. This switch allows the creation of a variable even if the environment variable already exists. Basically, the presence of the /Force+ switch transforms the creation process into an update process if the environment variable already exists (with the wbemChangeFlagCreateOrUpdate constant at line 178 versus the wbemChangeFlagCreateOnly constant at line 180). The environment variable creation is executed with the Put_ method of the new environment variable instance stored in an SWBemObject. Once the method executes, the code verifies that no error occurred during the creation (line 182). At that time, the new environment variable exists in the system or user environment. You can use the /Action:List switch to check its presence (or open a new command-line window and type the "set" command).

Sample 2.29: Updating environment variables (Part IV)

start example

 ...: ...: ...: 188: 189:    ' -- UPDATE ------------------------------------------------------------------------- 190:    If boolUpdate = True Then 191:       If boolUserEnv = True Then 192:          If Len(strUserEnv) = 0 Then 193:             objWMIInstance.UserName = WshNetwork.UserDomain & "\" & WshNetwork.UserName 194:          Else 195:             objWMIInstance.UserName = strUserEnv 196:          End If 197:       Else 198:          strUserName = "<SYSTEM>" 199:       End If 200: 201:       Set objWMIInstance = objWMIServices.Get _ 202:                 (cWMIClass & ".Name='" & strEnvVar & "',UserName='" & strUserName & "'") ...: 205:       objWMIInstance.VariableValue = strEnvVarValue 206: 207:       objWMIInstance.Put_ (wbemChangeFlagUpdateOnly Or wbemFlagReturnWhenComplete) ...: 211:       WScript.Echo "Environment variable '" & strEnvVar & "' updated." ...: 214:    End If 215: ...: ...: ...: 

end example

The update process of the environment variable almost follows the same logic as the variable creation. Of course, since we are in an update process, the script retrieves an instance of the environment variable given on the command line (lines 201 and 202). Next, the script updates the variable value (line 205). Once completed, the updated instance is saved with the Put_ method of the SWbemObject (line 207).

Sample 2.30: Deleting environment variables (Part V)

start example

 ...: ...: ...: 215: 216:    ' -- DELETE ------------------------------------------------------------------------- 217:    If boolDelete = True Then 218:       If boolUserEnv = True Then 219:          If Len(strUserEnv) = 0 Then 220:             objWMIInstance.UserName = WshNetwork.UserDomain & "\" & WshNetwork.UserName 221:          Else 222:             objWMIInstance.UserName = strUserEnv 223:          End If 224:       Else 225:          strUserName = "<SYSTEM>" 226:       End If 227: 228:       Set objWMIInstance = objWMIServices.Get _ 229:                  (cWMIClass & ".Name='" & strEnvVar & "',UserName='" & strUserName & "'") ...: 232:       objWMIInstance.Delete_ ...: 235:       WScript.Echo "Environment variable '" & strEnvVar & "' deleted." ...: 238:    End If ...: 242:    ]]> 243:    </script> 244:  </job> 245:</package> 237:</package> 

end example

To delete an environment variable, the script retrieves the existing Win32_Environment instance of the variable to be deleted (lines 228 and 229). Next, since the retrieved instance is stored in an SWbemObject, the Delete_ method is executed to delete the environment variable (line 232). No particular difficulty here!

2.4.3 Driver classes

The driver category classes represent the virtual device drivers and system drivers for base services. There are two classes are in this category (see Table 2.14).

Table 2.14: The Driver Classes

Name

Description

Win32_DriverVXD

Represents a virtual device driver on a Windows computer system.

Win32_SystemDriver

Represents the system driver for a base service.

The Win32_SystemDriver class is a subclass of the Win32_BaseService class. If you remember, throughout the first book, Understanding WMI Scripting, we worked a lot with the Win32_Service class. We saw that the Win32_Service class is also a child of Win32_BaseService (see Figure 2.11).


Figure 2.11: The CIM_Service class and its child classes.

If you look at the properties inheritance, you see that most of the properties and methods come from the Win32_BaseService class. This means that both classes share the same set of properties and methods and that most of the things valid for the Win32_Service class are also valid for the Win32_ SystemDriver. For reference, by using Sample 1.5 ("Listing all instances of a class with their properties formatted"), we obtain the following output:

  1:    C:\>GetCollectionOfInstances.wsf Win32_SystemDriver  2:    Microsoft (R) Windows Script Host Version 5.6  3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:  6:    AcceptPause: ............................. FALSE  7:    AcceptStop: .............................. FALSE  8:    Caption: ................................. Abiosdsk  9:    CreationClassName: ....................... Win32_SystemDriver 10:    Description: ............................. Abiosdsk 11:    DesktopInteract: ......................... FALSE 12:    DisplayName: ............................. Abiosdsk 13:    ErrorControl: ............................ Ignore 14:    ExitCode: ................................ 1077 15:    *Name: ................................... Abiosdsk 16:    ServiceSpecificExitCode: ................. 0 17:    ServiceType: ............................. Kernel Driver 18:    Started: ................................. FALSE 19:    StartMode: ............................... Disabled 20:    StartName: ............................... 21:    State: ................................... Stopped 22:    Status: .................................. OK 23:    SystemCreationClassName: ................. Win32_ComputerSystem 24:    SystemName: .............................. XP-DPEN6400 25:    TagId: ................................... 3 26: 27:    AcceptPause: ............................. FALSE 28:    AcceptStop: .............................. FALSE 29:    Caption: ................................. abp480n5 30:    CreationClassName: ....................... Win32_SystemDriver 31:    Description: ............................. abp480n5 32:    DesktopInteract: ......................... FALSE 33:    DisplayName: ............................. abp480n5 34:    ErrorControl: ............................ Normal 35:    ExitCode: ................................ 1077 36:    *Name: ................................... abp480n5 ..: ..: ..: 

Under Windows 95, 98, and Millennium, you will find instances of the Win32_DriverVXD class. With the same script, the output is as follows:

  1:    C:\>GetCollectionOfInstances.wsf Win32_DriverVXD  2:    Microsoft (R) Windows Script Host Version 5.6  3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:  6:    Caption: ................................. VMM  7:    Control: ................................. c0002788  8:    Description: ............................. VMM  9:    DeviceDescriptorBlock: ................... c0011330 10:    InstallDate: ............................. 11:    *Name: ................................... VMM 12:    OtherTargetOS: ........................... Win9X 13:    PM_API: .................................. c0002f30 14:    ServiceTableSize: ........................ 446 15:    *SoftwareElementID: ...................... VMM 16:    *SoftwareElementState: ................... 3 17:    Status: .................................. OK 18:    *TargetOperatingSystem: .................. 1 19:    V86_API: ................................. c0002f30 20:    *Version: ................................ 4,10 21: 22:    Caption: ................................. MTRR 23:    Control: ................................. c00403ec 24:    Description: ............................. MTRR 25:    DeviceDescriptorBlock: ................... c003f2a0 26:    InstallDate: ............................. 27:    *Name: ................................... MTRR 28:    OtherTargetOS: ........................... Win9X 29:    PM_API: .................................. 0 30:    ServiceTableSize: ........................ 4 31:    *SoftwareElementID: ...................... MTRR 32:    *SoftwareElementState: ................... 3 33:    Status: .................................. OK 34:    *TargetOperatingSystem: .................. 1 35:    V86_API: ................................. 0 36:    *Version: ................................ 1,00 37: 38:    Caption: ................................. VCACHE 39:    Control: ................................. c004ddf4 40:    Description: ............................. VCACHE 41:    DeviceDescriptorBlock: ................... c004eab8 42:    InstallDate: ............................. 43:    *Name: ................................... VCACHE 44:    OtherTargetOS: ........................... Win9X 45:    PM_API: .................................. c004e9c4 46:    ServiceTableSize: ........................ 29 47:    *SoftwareElementID: ...................... VCACHE 48:    *SoftwareElementState: ................... 3 49:    Status: .................................. OK 50:    *TargetOperatingSystem: .................. 1 51:    V86_API: ................................. c004e9c4 52:    *Version: ................................ 3,01 53: 54:    Caption: ................................. DFS 55:    Control: ................................. c007ac67 56:    Description: ............................. DFS 57:    DeviceDescriptorBlock: ................... c007ac0c 58:    InstallDate: ............................. 20-12-1998 19:52:16 59:    *Name: ................................... DFS 60:    OtherTargetOS: ........................... Win9X ..: ..: ..: 

2.4.4 File system classes

The file system category classes represent the way a hard disk is logically organized. This includes the type of file system used, the directory structure, and way the disk is partitioned. The classes included in this category are listed in Table 2.15.

Table 2.15: The File System Classes

Name

Type

Description

Win32_Directory

Dynamic

Represents a directory entry on a Windows computer system.

Win32_DirectorySpecification

Dynamic

Represents the directory layout for the product.

Win32_DiskPartition

Dynamic

Represents the capabilities and management capacity of a partitioned area of a physical disk on a Windows system.

Win32_QuotaSetting

Dynamic

Contains setting information for disk quotas on a volume.

Win32_ShortcutFile

Dynamic

Represents files that are shortcuts to other files, directories, and commands.

Win32_CIMLogicalDeviceCIMDataFile

Association

Relates logical devices and data files, indicating the driver files used by the device.

Win32_DiskDriveToDiskPartition

Association

Relates a disk drive and a partition existing on it.

Win32_DiskQuota

Association

Tracks disk space usage for NTFS volumes.

Win32_LogicalDiskRootDirectory

Association

Relates a logical disk and its directory structure.

Win32_LogicalDiskToPartition

Association

Relates a logical disk drive and the disk partition it resides on.

Win32_OperatingSystemAutochkSetting

Association

Represents the association between a CIM_ManagedSystemElement Dynamic and the settings defined for it.

Win32_SubDirectory

Association

Relates a directory (folder) and one of its subdirectories (subfolders).

Win32_SystemPartitions

Association

Relates a computer system and a disk partition on that system.

Win32_VolumeQuotaSetting

Association

Relates disk quota settings with a specific disk volume.

As we can see, this category includes the Win32_DiskQuota, Win32_ QuotaSetting, and Win32_VolumeQuotaSetting classes. These classes work in conjunction with the Disk Quota WMI provider, which is examined in the next chapter.

The Win32_ShortcutFile class is a subclass of the CIM_DataFile class. The CIM_DataFile class is a generic representation of a file. The CIM_DataFile class is also a superclass for classes such as Win32_CodecFile, Win32_NTEventLogFile, and Win32_PageFile. Note that the Win32_NTEventLogFile class is supported by the MS_NT_EVENTLOG_PROVIDER provider and will be examined in the next chapter, since this class is supported by a provider other than the Win32 provider.

The Win32_Directory class is a subclass of the CIM_Directory. However, this class is the only subclass of CIM_Directory class. The CIM_DataFile relationships are shown in Figure 2.12.


Figure 2.12: The CIM_LogicalFile class and its child classes.

To gather information about a file, it is best to use the CIM_DataFile class, because it is the most generic file representation. The existing subclasses are too specific to a particular file type. Since there are thousands of files in a file system, it is better to retrieve a single instance of a file than a collection. For example, to retrieve information related to the BOOT.INI file, we can use Sample 1.4 ("Listing a single instance of a class with its properties formatted"):

  1:    C:\>GetSingleInstance CIM_DataFile "'C:\Boot.Ini"'  2:    Microsoft (R) Windows Script Host Version 5.6  3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:    AccessMask: .............................. 18809343  6:    Archive: ................................. FALSE  7:    Caption: ................................. c:\boot.ini  8:    Compressed: .............................. FALSE  9:    CreationClassName: ....................... CIM_LogicalFile 10:    CreationDate: ............................ 03-05-2001 12:53:02 11:    CSCreationClassName: ..................... Win32_ComputerSystem 12:    CSName: .................................. XP-DPEN6400 13:    Description: ............................. c:\boot.ini 14:    Drive: ................................... c: 15:    EightDotThreeFileName: ................... c:\boot.ini 16:    Encrypted: ............................... FALSE 17:    Extension: ............................... ini 18:    FileName: ................................ boot 19:    FileSize: ................................ 199 20:    FileType: ................................ Configuration Settings 21:    FSCreationClassName: ..................... Win32_FileSystem 22:    FSName: .................................. NTFS 23:    Hidden: .................................. TRUE 24:    InstallDate: ............................. 03-05-2001 12:53:02 25:    LastAccessed: ............................ 20-10-2001 22:26:07 26:    LastModified: ............................ 20-10-2001 22:26:07 27:    *Name: ................................... c:\boot.ini 28:    Path: .................................... \ 29:    Readable: ................................ TRUE 30:    Status: .................................. OK 31:    System: .................................. TRUE 32:    Writeable: ............................... TRUE 

This output summarizes the typical properties of a file. Note at line 5 that the AccessMask property is a bit array representing the access rights to the given file held by the user or group on whose behalf the instance is returned. We revisit the access mask and the rights granted on the file system in Chapter 4, when we examine the Security WMI provider. The same operation can be repeated with the CIM_Directory class; the output is as follows:

  1:    C:\>GetSingleInstance CIM_Directory "'C:\Windows'"  2:    Microsoft (R) Windows Script Host Version 5.6  3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:    Archive: ................................. FALSE  6:    Caption: ................................. C:\Windows  7:    Compressed: .............................. FALSE  8:    CreationClassName: ....................... CIM_LogicalFile  9:    CreationDate: ............................ 03-05-2001 03:44:03 10:    CSCreationClassName: ..................... Win32_ComputerSystem 11:    CSName: .................................. XP-DPEN6400 12:    Description: ............................. C:\Windows 13:    Drive: ................................... j: 14:    EightDotThreeFileName: ................... C:\Windows 15:    Encrypted: ............................... FALSE 16:    Extension: ............................... 17:    FileName: ................................ windows 18:    FileType: ................................ File Folder 19:    FSCreationClassName: ..................... Win32_FileSystem 20:    FSName: .................................. NTFS 21:    Hidden: .................................. FALSE 22:    InstallDate: ............................. 03-05-2001 03:44:03 23:    LastAccessed: ............................ 21-10-2001 14:37:08 24:    LastModified: ............................ 21-10-2001 12:08:30 25:    *Name: ................................... C:\Windows 26:    Path: .................................... \ 27:    Readable: ................................ TRUE 28:    Status: .................................. OK 29:    System: .................................. FALSE 30:    Writeable: ............................... TRUE 

Since we examine the file system, we must also examine the Win32_DiskPartition class, since a disk partition generally contains a file system. Examining the Win32_DiskPartition class implies the examination of some classes that have an association with the Win32_DiskPartition class, such as the Win32_LogicalDisk and Win32_DiskDrive classes examined previously in section 2.3.2 ("Mass storage classes"). Figure 2.13 represents the association relationship seen from the Win32_DiskPartition class.

click to expand
Figure 2.13: The Win32_ DiskPartition class associations.

The purpose of Samples 2.31 through 2.34 is to retrieve information about these classes.

Sample 2.31: Gathering disk partition, disk drive, and logical disk information (Part I)

start example

  1:<?xml version="1.0"?>  .:  8:<package>  9:  <job> ..: 13:    <runtime> ..: 17:    </runtime> 18: 19:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodeDeviceAvailabilityFunction.vbs" /> 20:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodeCfgManErrCodeFunction.vbs" /> 21:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodeStatusInfoFunction.vbs" /> 22:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodePwrManCapabilitiesFunction.vbs" /> 23:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodeDiskCapabilitiesFunction.vbs" /> 24: 25:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" /> 26:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" /> 27: 28:    <object prog  reference="true"/> 29:    <object prog  /> 30: 31:    <script language="VBscript"> 32:    <![CDATA[ ..: 36:    Const cComputerName = "LocalHost" 37:    Const cWMINameSpace = "root/cimv2" ..: 52:    ' -------------------------------------------------------------------------------- 53:    ' Parse the command line parameters 54:    strUserID = WScript.Arguments.Named("User") ..: 61:    If Len(strComputerName) = 0 Then strComputerName = cComputerName ..: 66:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 67:                                                     strUserID, strPassword) ..: 69: ..: ..: ..: 

end example

Once again, the code starts by including the external functions (lines 19 through 26) and defining and parsing the command-line parameters (skipped lines 13 through 17 and $4 through 61) before establishing the WMI connection (lines 66 and 67). Once completed, the script examines the Win32_DiskPartition instances (see Sample 2.32).

Sample 2.32: Gathering disk partition information (Part II)

start example

  ..:  ..:  ..:  69:  70:    Set objWMIInstances = objWMIServices.InstancesOf ("Win32_DiskPartition")  ..:  73:    If objWMIInstances.Count Then  74:       For Each objWMIInstance In objWMIInstances  75:           WScript.Echo "- " & objWMIInstance.DeviceID & " " & String (61, "-")  76:  77:           Set objWMIPropertySet = objWMIInstance.Properties_  78:           For Each objWMIProperty In objWMIPropertySet  79:               Select Case objWMIProperty.Name  80:                      Case "Availability"  81:                           DisplayFormattedProperty objWMIInstance, _  82:                                      "  " & objWMIProperty.Name, _  83:                                      DeviceAvailability (objWMIInstance.Availability), _  84:                                      Null ...: 100:                      Case "StatusInfo" 101:                           DisplayFormattedProperty objWMIInstance, _ 102:                                      "  " & objWMIProperty.Name, _ 103:                                      StatusInfo (objWMIInstance.StatusInfo), _ 104:                                      Null 105:                      Case "CreationClassName" 106: 107:                      Case "SystemCreationClassName" 108: 109:                      Case "SystemName" 110: 111:                      Case "Caption" 112: 113:                      Case "Name" 114: 115:                      Case Else 116:                           DisplayFormattedProperty objWMIInstance, _ 117:                                      "  " & objWMIProperty.Name, _ 118:                                      objWMIProperty.Name, _ 119:                                      Null 120:               End Select 121:           Next 122:           Set objWMIPropertySet = Nothing 123: ...: ...: ...: 

end example

To explore the Win32_DiskPartition instances, the script contains nothing unusual compared with the previous script developed. Sample 2.32 is only provided for reference. However, since a disk partition is located on a disk drive, to gather information about the Win32_DiskDrive instance associated with the Win32_DiskPartition instance, the script retrieves the information by using the Win32_DiskDriveToDiskPartition association class (see Figure 2.13). This code is available in Sample 2.33 from lines 124 through 127.

Sample 2.33: Gathering disk drive information (Part III)

start example

 ...: ...: ...: 123: 124:            Set objWMIPhysicalDiskInstances = objWMIServices.ExecQuery _ 125:                                          ("Associators of {Win32_DiskPartition='" & _ 126:                                          objWMIInstance.DeviceID & _ 127:                                          "'} Where AssocClass=Win32_DiskDriveToDiskPartition") 128: 129:            If objWMIPhysicalDiskInstances.Count Then 130:               WScript.Echo 131:               WScript.Echo " -- Physical disk information " & " " & String (53, "-") 132:               For Each objWMIPhysicalDiskInstance In objWMIPhysicalDiskInstances 133:                   Set objWMIPropertySet = objWMIPhysicalDiskInstance.Properties_ 134:                   For Each objWMIProperty In objWMIPropertySet 135:                       Select Case objWMIProperty.Name 136:                              Case "Availability" 137:                                   DisplayFormattedProperty objWMIPhysicalDiskInstance, _ 138:                                          "  " & objWMIProperty.Name, _ ...: 156:                              Case "StatusInfo" 157:                                   DisplayFormattedProperty objWMIPhysicalDiskInstance, _ 158:                                          "  " & objWMIProperty.Name, _ 159:                                          StatusInfo (objWMIPhysicalDiskInstance.StatusInfo), _ 160:                                          Null 161:                              Case "CreationClassName" 162: 163:                              Case "SystemCreationClassName" 164: 165:                              Case "SystemName" 166: 167:                              Case "Caption" 168: 169:                              Case "Name" 170: 171:                              Case "Capabilities" 172:                                   DisplayFormattedProperty objWMIPhysicalDiskInstance, _ 173:                                          "  " & objWMIProperty.Name, _ ...: 177:                              Case Else 178:                                   DisplayFormattedProperty objWMIPhysicalDiskInstance, _ 179:                                          "  " & objWMIProperty.Name, _ 180:                                          objWMIProperty.Name, _ 181:                                          Null 182:                       End Select 183:                   Next 184:                   Set objWMIPropertySet = Nothing 185:               Next 186:            End If 187: 188:            Set objWMIPhysicalDiskInstances = Nothing 189: ...: ...: ...: 

end example

Again, the display of the Win32_DiskDrive properties is executed as before. In the same way, since a disk partition hosts a logical disk, it is interesting to gather information about it. By using the Win32_LogicalDiskTo-Partition association class, it is possible to retrieve the Win32_LogicalDisk instances for the Win32_DiskPartition (see Figure 2.13). Sample 2.34 executes this operation from lines 190 through 193. Next, the script displays the properties of the retrieved instances (lines 198 through 268).

Sample 2.34: Gathering logical disk information (Part IV)

start example

 ...: ...: ...: 189: 190:           Set objWMILogicalDiskInstances = objWMIServices.ExecQuery _ 191:                     ("Associators of {Win32_DiskPartition='" & _ 192:                     objWMIInstance.DeviceID & _ 193:                     "'} Where AssocClass=Win32_LogicalDiskToPartition") 194: 195:           If objWMILogicalDiskInstances.Count Then 196:              WScript.Echo 197:              WScript.Echo " -- Logical disk information " & " " & String (55, "-") 198:              For Each objWMILogicalDiskInstance In objWMILogicalDiskInstances 199:                  Set objWMIPropertySet = objWMILogicalDiskInstance.Properties_ 200:                  For Each objWMIProperty In objWMIPropertySet 201:                      Select Case objWMIProperty.Name 202:                             Case "Availability" 203:                                  DisplayFormattedProperty objWMILogicalDiskInstance, _ 204:                                         "  " & objWMIProperty.Name, _ ...: 232: 233:                             Case "Caption" 234: 235:                             Case "Name" 236: 237:                             Case Else 238:                                  DisplayFormattedProperty objWMILogicalDiskInstance, _ 239:                                         "  " & objWMIProperty.Name, _ 240:                                         objWMIProperty.Name, _ 241:                                         Null 242:                      End Select 243:                  Next 244:                  Set objWMIPropertySet = Nothing 245: ...: ...: ...: 267: 268:              Next 269:              Set objWMILogicalDiskInstances = Nothing 270:           End If 271: 272:           WScript.Echo 273:       Next 274:    Else 275:       WScript.Echo "No information available." 276:    End If ...: 281:    ]]> 282:    </script> 283:  </job> 284:</package> 

end example

Notice that between lines 245 and 267 we have a certain number of lines missing. This part of the code examines the quotas set on the logical disk. We examine this code in the next chapter, since it relates to the use of the Win32_DiskQuota, Win32_QuotaSetting, and Win32_VolumeQuotaSetting classes supported by the Disk Quota WMI provider.

Once the script is started, you obtain the following output:

  1:    C:\>GetPartitionInformation.wsf  2:    Microsoft (R) Windows Script Host Version 5.6  3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:    - Disk #1, Partition #0 -------------------------------------------------------------  6:      BlockSize: ............................. 512  7:      Description: ........................... MS-DOS V4 Huge  8:      *DeviceID: ............................. Disk #1, Partition #0  9:      DiskIndex: ............................. 1 10:      Index: ................................. 0 11:      InstallDate: ........................... 01-01-2000 12:      NumberOfBlocks: ........................ 4188177 13:      PrimaryPartition: ...................... FALSE 14:      Size: .................................. 2144346624 15:      StartingOffset: ........................ 32256 16:      Type: .................................. MS-DOS V4 Huge 17: 18:      -- Physical disk information ----------------------------------------------------- 19:      BytesPerSector: ........................ 512 20:      Capabilities: .......................... Random Access, Supports Writing 21:      ConfigManagerErrorCode: ................ This device is working properly. 22:      ConfigManagerUserConfig: ............... FALSE 23:      Description: ........................... Disk drive 24:      *DeviceID: ............................. \\.\PHYSICALDRIVE1 25:      Index: ................................. 1 26:      InstallDate: ........................... 01-01-2000 27:      InterfaceType: ......................... IDE 28:      Manufacturer: .......................... (Standard disk drives) 29:      MediaLoaded: ........................... TRUE 30:      MediaType: ............................. Fixed hard disk media 31:      Model: ................................. FUJITSU MPC310AT E 32:      Partitions: ............................ 4 33:      PNPDeviceID: ........................... IDE\DSKFUJITSU_MPC310AT_E_CD05_\4&8F1A1C8&0&0.1.0 34:      SCSIBus: ............................... 0 35:      SCSILogicalUnit: ....................... 0 36:      SCSIPort: .............................. 0 37:      SCSITargetId: .......................... 1 38:      SectorsPerTrack: ....................... 63 39:      Signature: ............................. 2101398628 40:      Size: .................................. 10001940480 41:      Status: ................................ OK 42:      TotalCylinders: ........................ 1292 43:      TotalHeads: ............................ 240 44:      TotalSectors: .......................... 19535040 45:      TotalTracks: ........................... 310080 46:      TracksPerCylinder: ..................... 240 47: 48:      -- Logical disk information ------------------------------------------------------- 49:      Compressed: ............................ FALSE 50:      Description: ........................... Local Fixed Disk 51:      *DeviceID: ............................. D: 52:      DriveType: ............................. 3 53:      FileSystem: ............................ FAT 54:      FreeSpace: ............................. 497254400 55:      InstallDate: ........................... 01-01-2000 56:      MaximumComponentLength: ................ 255 57:      MediaType: ............................. 12 58:      Size: .................................. 2144043008 59:      SupportsDiskQuotas: .................... FALSE 60:      SupportsFileBasedCompression: .......... FALSE 61:      VolumeDirty: ........................... FALSE 62:      VolumeName: ............................ APPS 63:      VolumeSerialNumber: .................... 4C2002DB ..: ..: ..: 

Instead of developing some passive scripts, we can use the classes in the File System category differently. For instance, by using the CIM_DataFile class, it is possible to watch the growth of a file. This is interesting if you want to monitor the physical size of database files (i.e., Exchange 2000 Information Store size). In section 2.3.2, we developed a script that monitors the free disk space (see Sample 2.2, "Alerting script when the free disk space decreases below 50 percent on a specific disk"). We can develop the same kind of script, but instead of monitoring the free disk space diminutions, we can monitor the growth of a selected file. The code is shown in Sample 2.35.

Sample 2.35: Watching a file size

start example

  1:<?xml version="1.0"?>  .:  8:<package>  9:  <job> ..: 13:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" /> 14:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\PauseScript.vbs" /> 15: 16:    <reference object="WbemScripting.SWbemLocator"/> 17: 18:    <script language="VBscript"> 19:    <![CDATA[ ..: 23:    ' ---------------------------------------------------------------------------------------- 24:    Const cComputerName = "LocalHost" 25:    Const cWMINameSpace = "root/cimv2" 26:    Const cWMIClass = "CIM_DataFile" 27:    Const cWMIInstance = "'E:\\TEST.TXT'" 28:    Const cFileSize = 10240 ..: 36:    Set objWMISink = WScript.CreateObject ("WbemScripting.SWbemSink", "SINK_") 37: 38:    Set objWMIServices = GetObject("WinMgmts:{impersonationLevel=impersonate}!//" & _ 39:                                   cComputerName & "/" & cWMINameSpace) ..: 42:    strWQLQuery = "Select * From __InstanceModificationEvent Within 10 " & _ 43:                  "Where TargetInstance ISA '" & cWMIClass & "' And " & _ 44:                  "TargetInstance.Name=" & cWMIInstance & " And " & _ 45:                  "TargetInstance.FileSize > " & cFileSize & " And " & _ 46:                  "TargetInstance.FileSize > PreviousInstance.FileSize" 47: 48:    objWMIServices.ExecNotificationQueryAsync objWMISink, _ 49:                                              strWQLQuery, _ 50:                                              , _ 51:                                              wbemFlagSendStatus ..: 54:    WScript.Echo "Waiting for events..." 55: 56:    PauseScript "Click on 'Ok' to terminate the script ..." 57: 58:    WScript.Echo vbCRLF & "Cancelling event subscription ..." 59:    objWMISink.Cancel ..: 64:    WScript.Echo "Finished." 65: 66:    ' ----------------------------------------------------------------------------------------- 67:    Sub SINK_OnObjectReady (objWbemObject, objWbemAsyncContext) ..: 73:        Wscript.Echo 74:        WScript.Echo FormatDateTime(Date, vbLongDate) & " at " & _ 75:                     FormatDateTime(Time, vbLongTime) & "." 76: 77:        WScript.Echo "Warning, file " & UCase (objWbemObject.TargetInstance.Name) & " has " & _ 78:                        objWbemObject.TargetInstance.FileSize & _ 79:                        " bytes of size." 80: 81:    End Sub 82: 83:    ]]> 84:   </script> 85:  </job> 86:</package> 

end example

If Sample 2.35 is compared with Sample 2.2, it is almost the same script. The major difference resides in the WQL query (lines 42 through 46):

 1:  Select * From __InstanceModificationEvent Within 10 2:        Where TargetInstance ISA 'CIM_DataFile' And 3:        TargetInstance.Name=" &  E:\\TEST.TXT' And 4:        TargetInstance.FileSize > 10240 And 5:        TargetInstance.FileSize > PreviousInstance.FileSize 

The WQL query contains four conditions, based on:

  • The TargetInstance class type (line 2): This condition makes sense, since the monitoring must be executed on an instance of the CIM_DataFile.

  • The Name (line 3): Because the monitoring must be done on a specific file name.

  • The FileSize (line 4): The FileSize is the current size of the file instance. If we do not want the script to send an alert if the size is less than 10,240 bytes (10 K), this requirement must be included in the condition statement.

  • The file growth (line 5): Since the requirement is to send an alert only when the file size increases, the test evaluates the size of the file instance with the value of the previous file instance. If the current instance size is greater, it means that the file size increases.

Once this WQL event query is submitted, and when the examined file meets these conditions, the event sink routine SINK_OnObjectReady() (lines 67 through 81) is called, and a message containing the file size information is displayed on the screen (lines 77 through 79).

If you look at the CIM_DataFile class and CIM_Directory class methods, you see that they share the same methods. These two classes are subclasses of the CIM_LogicalFile class, which is the CIM origin of the method definitions. Table 2.16 shows the CIM_LogicalFile methods.

Table 2.16: The CIM_LogicalFile Methods

Method name

Description

TakeOwnerShip

Class method that obtains ownership of the logical file specified in the object path.

ChangesecurityPermissions

Class method that changes the security permissions for the logical file specified in the object path.

Copy

Class method that copies the logical file or directory specified in the object path to the location specified by the input parameter.

Rename

Class method that renames the logical file (or directory) specified in the object path.

Delete

Class method that deletes the logical file (or directory) specified in the object path.

Compress

Class method that compresses the logical file (or directory) specified in the object path.

Uncompress

Class method that uncompresses the logical file (or directory) specified in the object path.

TakeOwnerShipEx

Class method that obtains ownership of the logical file specified in the object path.

ChangesecurityPermissionsEx

Class method that changes the security permissions for the logical file specified in the object path.

CopyEx

Class method that copies the logical file or directory specified in the object path to the location specified by the FileName parameter.

DeleteEx

Class method that deletes the logical file (or directory) specified in the object path.

CompressEx

Class method that compresses the logical file (or directory) specified in the object path.

UncompressEx

Class method that uncompresses the logical file (or directory) specified in the object path.

GetEffectivePermission

Class method that determines whether the caller has the aggregated permissions specified by the Permission argument not only on the file object, but on the share the file or directory resides on (if it is on a share).

By using these methods it is possible to copy, rename, delete, compress or decompress, and take ownership of any file or directory. Using the method at the level of the CIM_LogicalFile class permits the equal manipulation of files or directories. Sample 2.36 shows how to proceed. The command-line parameters required are:

 C:\>WMIFileMan.Wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIFileMan.wsf Operation Source [target] [/recursive[+|-]] [/Machine:value]                                        [/User:value] [/Password:value] Options: Operation : Operation to perform. Only [Copy], [Rename], [Delete], [Compress],             [Uncompress] and [TakeOwnerShip] are accepted. Source    : The source file name or directory. target    : The target file name or directory (if required by the operation). recursive : Perform the operation recursively (if supported by the operation). 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:       WMIFileMan Copy C:\BOOT.INI D:\BOOT.INI       WMIFileMan Copy "C:\Program Files" "D:\Program Files" /Recursive+       WMIFileMan Compress "D:\Program Files" /Recursive+       WMIFileMan TakeOwnership "D:\Program Files"       WMIFileMan Delete "D:\Program Files" 

Sample 2.36: Copying, renaming, deleting, (un)compressing, and taking ownership of files and directories.

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  30:    </runtime>  31:  32:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodeWin32_DirectoryRCFunction.vbs" />  33:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  34:  35:    <object prog  reference="true"/>  36:  37:    <script language="VBscript">  38:    <![CDATA[  ..:  42:    Const cComputerName = "LocalHost"  43:    Const cWMINameSpace = "root/cimv2"  44:    Const cWMIClass = "CIM_LogicalFile"  ..:  66:    ' --------------------------------------------------------------------------------  67:    ' Parse the command line parameters  68:    If WScript.Arguments.Unnamed.Count = 0 Then  69:       WScript.Arguments.ShowUsage()  70:       WScript.Quit  71:    Else  72:       strWMIOperation = Ucase(WScript.Arguments.Unnamed.Item(0))  73:    End If  74:  75:    boolRecursive = WScript.Arguments.Named("Recursive")  76:    If Len(boolRecursive) = 0 Then boolRecursive = False  77:  78:    Select Case strWMIOperation  79:           Case "COPY"  80:                If WScript.Arguments.Unnamed.Count < 3 Then  ..:  84:                Else  85:                   strWMISourceInstance = WScript.Arguments.Unnamed.Item(1)  86:                   strWMITargetInstance = WScript.Arguments.Unnamed.Item(2)  87:                End If  88:  89:           Case "RENAME"  90:                If WScript.Arguments.Unnamed.Count < 3 Then  ..:  94:                Else  95:                   strWMISourceInstance = WScript.Arguments.Unnamed.Item(1)  96:                   strWMITargetInstance = WScript.Arguments.Unnamed.Item(2)  97:                End If  98:  99:           Case "DELETE" 100:                If WScript.Arguments.Unnamed.Count < 2 Then ...: 104:                Else 105:                   strWMISourceInstance = WScript.Arguments.Unnamed.Item(1) 106:                End If 107: 108:           Case "COMPRESS" 109:                If WScript.Arguments.Unnamed.Count < 2 Then ...: 113:                Else 114:                   strWMISourceInstance = WScript.Arguments.Unnamed.Item(1) 115:                End If 116: 117:           Case "UNCOMPRESS" 118:                If WScript.Arguments.Unnamed.Count < 2 Then ...: 122:                Else 123:                   strWMISourceInstance = WScript.Arguments.Unnamed.Item(1) 124:                End If 125: 126:           Case "TAKEOWNERSHIP" 127:                If WScript.Arguments.Unnamed.Count < 2 Then ...: 135:           Case Else 136:                WScript.Echo "Invalid action. Only [Copy], [Rename], ..." & vbCRLF 137:                WScript.Arguments.ShowUsage() 138:                WScript.Quit (1) 139:    End Select 140: 141:    strUserID = WScript.Arguments.Named("User") ...: 148:    If Len(strComputerName) = 0 Then strComputerName = cComputerName ...: 153:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 154:                                                     strUserID, strPassword) ...: 157:    Set objWMIInstance = objWMIServices.Get (cWMIClass & "='" & _ 158:                                             strWMISourceInstance & "'") 159:    Select Case UCase(strWMIOperation) 160:           Case "COPY" 161:                 WScript.Echo strWMIOperation & " of '" & strWMISourceInstance & _ 162:                              "' to '" & strWMITargetInstance & _ 163:                              "' (Recursive=" & boolRecursive & ")." 164:                 WScript.Echo "Operation in progress on '" & _ 165:                              strComputerName & "', please wait ..." 166:                 intRC = objWMIInstance.CopyEX (strWMITargetInstance, _ 167:                                                strStopFileName, _ 168:                                                strStartFileName, _ 169:                                                boolRecursive) 170:           Case "RENAME" 171:                 WScript.Echo strWMIOperation & " of '" & strWMISourceInstance & _ 172:                              "' to '" & strWMITargetInstance & "'." 173:                 WScript.Echo "Operation in progress on '" & _ 174:                              strComputerName & "', please wait ..." 175:                 intRC = objWMIInstance.Rename (strWMITargetInstance) 176:           Case "DELETE" 177:                 WScript.Echo strWMIOperation & " of '" & strWMISourceInstance & "'." 178:                 WScript.Echo "Operation in progress on '" & _ 179:                              strComputerName & "', please wait ..." 180:                 intRC = objWMIInstance.Delete (strStopFileName, _ 181:                                                strStartFileName) 182:           Case "COMPRESS" 183:                 WScript.Echo strWMIOperation & " of '" & strWMISourceInstance & _ 184:                              "' (Recursive=" & boolRecursive & ")." 185:                 WScript.Echo "Operation in progress on '" & _ 186:                              strComputerName & "', please wait ..." 187:                 intRC = objWMIInstance.Compress (strStopFileName, _ 188:                                                  strStartFileName, _ 189:                                                  boolRecursive) 190:           Case "UNCOMPRESS" 191:                 WScript.Echo strWMIOperation & " of '" & strWMISourceInstance & _ 192:                              "' (Recursive=" & boolRecursive & ")." 193:                 WScript.Echo "Operation in progress on '" & _ 194:                              strComputerName & "', please wait ..." 195:                 intRC = objWMIInstance.UnCompress (strStopFileName, _ 196:                                                    strStartFileName, _ 197:                                                    boolRecursive) 198:           Case "TAKEOWNERSHIP" 199:                 WScript.Echo strWMIOperation & " of '" & strWMISourceInstance & _ 200:                              "' (Recursive=" & boolRecursive & ")." 201:                 WScript.Echo "Operation in progress on '" & _ 202:                              strComputerName & "', please wait ..." 203:                 intRC = objWMIInstance.TakeOwnerShipEx (strStopFileName, _ 204:                                                         strStartFileName, _ 205:                                                         boolRecursive) 206:    End Select 207: 208:    WScript.Echo UCase(strWMIOperation) & ": " & Win32_DirectoryRC(intRC) 209:    If intRC Then 210:       WScript.Echo "Failed " & UCase(strWMIOperation) & _ 211:                    " operation on '" & Ucase (strStopFileName) & "'." 212:    End If ...: 217:    ]]> 218:    </script> 219:  </job> 220:</package> 

end example

As usual, the script defines and parses the command-line parameters (skipped lines 13 through 30 and 68 through 148). Next, based on the command-line parameters, the corresponding method is executed. Each method has its own set of parameters:

  • Copy method (from line 160 through 169): The CopyEx method is invoked instead of the Copy method, because the CopyEx method exposes a parameter to perform recursive copies. This can be useful when copying a directory with its subdirectories. It is important to note that the copy operation is not supported if it overwrites an existing Win32_LogicalFile instance.

  • Rename method (from line 170 through 175): The Rename Win32_LogicalFile class method renames a Win32_LogicalFile instance specified in the path. The rename is not supported if the destination is on another drive or if it overwrites an existing Win32_LogicalFile instance.

  • Delete method (from line 176 through 181): This method simply deletes a Win32_LogicalFile instance. Note that in the case of a directory, if subdirectories exist, they will also be deleted.

  • Compress method (from line 182 through 189): Again, the CompressEx method is used instead of the Compress method, because the CompressEx method exposes a parameter to perform the recursive compression. The same rule applies for the uncompress operation.

  • UnCompress method (from line 190 through 197): See Compress method.

  • TakeOwnerShip method (from line 198 through 205): The TakeOwnerShip method obtains ownership of the Win32_LogicalFile instance specified in the object path. If the logical file is a directory, and if the /Recursive+ switch is given, then the TakeOwnerShip method acts recursively, taking ownership of all the files and subdirectories the directory contains. It is important to note that the user running the script becomes the owner. Currently, it is impossible to set the owner for another user account with this method. Even if the WMI connection is done with other credentials (/User and /Password switch), the user who starts the script is the one set as the owner. By editing the security descriptor, it is also possible to change the owner. We will see how to proceed when examining the Security provider in Chapter 4.

Because Sample 2.36 utilizes the extended methods of the Win32_LogicalFile class, it is possible, in case of error, to determine the name of the file or directory where the problem occurred. This information is displayed at lines 210 and 211. Note that by using a different script structure, it is possible to restart the operation by using the StartFileName method parameter to recover the execution of the Win32_LogicalFile method from the point of failure.

2.4.5 Page file classes

The page file information class category retrieves information about the page file settings. This includes the page file settings and usage. The classes included in this category are listed in Table 2.17.

Table 2.17: The Page File Classes

Name

Type

Description

Win32_LogicalMemoryConfiguration

Dynamic

This class is obsolete and has been replaced by the Win32_OperatingSystem class.

Win32_PageFile

Dynamic

Represents the file used for handling virtual memory file swapping

Win32_PageFileSetting

Dynamic

Represents the settings of a page file.

Win32_PageFileUsage

Dynamic

Represents the file used for handling virtual memory file swapping on a Windows system.

Win32_PageFileElementSetting

Association

Relates the initial settings of a page file and the state of those settings during normal use.

Win32_SystemLogicalMemoryConfiguration

Association

This class is obsolete, because the properties existing in the Win32_LogicalMemoryConfiguration class are now a part of the Win32_OperatingSystem class.

More than simply retrieving the page file setting, the use of the Win32_ PageFile class allows the creation, modification, and deletion of a page file. The technique is very similar to the script technique used in Samples 2.26 through 2.30 ("Reading, creating, updating, and deleting environment variables"). Of course, the set of parameters is different. Let's see what the parameters are.

 C:\>WMIPageFile.wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIPageFile.wsf PageFileName /Action:value [/SetInitialSize:value] [/SetMaximumSize:value]                                    [/Machine:value] [/User:value] [/Password:value] Options: PageFileName   : Define the name of the pagefile to configure. Action         : specify the operation to perform: [create] or [update] or [delete]. SetInitialSize : Set the initial size of the pagefile. SetMaximumSize : Set the maximum size of the pagefile. 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:       WMIPageFile.wsf /Action:List       WMIPageFile.wsf C:\PAGEFILE.SYS /SetInitialSize:128 /SetMaximumSize:256 /Action:Create       WMIPageFile.wsf C:\PAGEFILE.SYS /SetInitialSize:256 /SetMaximumSize:512 /Action:Update       WMIPageFile.wsf C:\PAGEFILE.SYS /Action:Delete 

Basically, the usual four basic operations can be executed: viewing, creating, updating, and deleting. Since a page file has an initial and a maximum size, these parameters also can be set from the command line. Samples 2.37 through 2.41 show how to proceed.

Sample 2.37: Viewing, creating, updating, and deleting page files (Part I)

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  29:    </runtime>  30:  31:    <script language="VBScript" src="/books/2/679/1/html/2/.\Functions\DisplayFormattedPropertyFunction.vbs" />  32:    <script language="VBScript" src="/books/2/679/1/html/2/.\Functions\TinyErrorHandler.vbs" />  33:  34:    <object prog  reference="true"/>  35:    <object prog  />  36:  37:    <script language="VBscript">  38:    <![CDATA[  ..:  42:    Const cComputerName = "LocalHost"  43:    Const cWMINameSpace = "root/cimv2"  44:    Const cWMIPageFileClass = "Win32_PageFile"  45:    Const cWMIPageFileUsageClass = "Win32_PageFileUsage"  ..:  73:    ' --------------------------------------------------------------------------------  74:    ' Parse the command line parameters  75:    If WScript.Arguments.Named.Count Then  76:       Select Case Ucase(WScript.Arguments.Named("Action"))  77:              Case "LIST"  78:                   boolList = True  79:              Case "CREATE"  80:                   boolCreate = True  81:              Case "UPDATE"  82:                   boolUpdate = True  83:              Case "DELETE"  84:                   boolDelete = True  85:              Case Else  86:                   WScript.Echo "Invalid action type. Only [list], ..." & vbCRLF  87:                   WScript.Arguments.ShowUsage()  88:                   WScript.Quit  89:       End Select  90:    End If  91:  92:    If (WScript.Arguments.Unnamed.Count = 0 And boolList = False) Or _  93:       (WScript.Arguments.Unnamed.Count <> 0 And boolList = True) Then  94:       WScript.Arguments.ShowUsage()  95:       WScript.Quit  96:    Else  97:       If WScript.Arguments.Unnamed.Count Then  98:          strWMIInstanceName = WScript.Arguments.Unnamed.Item(0)  99:       End If 100:    End If 101: 102:    longInitialSize = CLng(WScript.Arguments.Named("SetInitialSize")) 103:    If longInitialSize > 0 Then boolInitialSize = True 104: 105:    longMaximumSize = CLng(WScript.Arguments.Named("SetMaximumSize")) 106:    If longMaximumSize > 0 Then boolMaximumSize = True 107: 108:    strUserID = WScript.Arguments.Named("User") ...: 115:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 116: 117:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 118:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 119:    objWMILocator.Security_.Privileges.AddAsString "SeCreatePagefilePrivilege", True 120: 121:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 122:                                                     strUserID, strPassword) 123:    If Err.Number Then ErrorHandler (Err) 124: ...: ...: ...: 

end example

This first part of the script is very common now. Nothing unusual, except a command-line definition (lines 13 through 29) and parsing (lines 74 through 115) adapted to the page file needs.

The first basic operation is coded in Sample 2.38. The purpose is to show the page file properties.

Sample 2.38: Viewing page files (Part II)

start example

 ...: ...: ...: 124: 125:    ' -- LIST --------------------------------------------------------------------------- 126:    If boolList = True Then 127:       Set objWMIInstances = objWMIServices.InstancesOf (cWMIPageFileClass) ...: 130:       For Each objWMIInstance in objWMIInstances 131:           WScript.Echo "- " & Ucase(objWMIInstance.Name) & String (60, "-") 132:           Set objWMIPropertySet = objWMIInstance.Properties_ 133:           For Each objWMIProperty In objWMIPropertySet 134:               Select Case objWMIProperty.Name 135:                      Case "Caption" ...: 147:                      Case Else 148:                           DisplayFormattedProperty objWMIInstance, _ 149:                                                    "  " & objWMIProperty.Name, _ 150:                                                    objWMIProperty.Name, _ 151:                                                    Null 152:               End Select 153:           Next 154:           Set objWMIPropertySet = Nothing 155: 156:           WScript.Echo 157: 158:           Set objWMIPageFileUsage = objWMIServices.Get (cWMIPageFileUsageClass & "='" & _ 159:                                                         objWMIInstance.Name & "'") ...: 162:          Set objWMIPropertySet = objWMIPageFileUsage.Properties_ 163:          For Each objWMIProperty In objWMIPropertySet 164:              Select Case objWMIProperty.Name 165:                     Case "AllocatedBaseSize" ...: 175:                     Case Else 176:                          DisplayFormattedProperty objWMIPageFileUsage, _ 177:                                                   "  " & objWMIProperty.Name, _ 178:                                                   objWMIProperty.Name, _ 179:                                                   Null 180:              End Select 181:          Next 186:           WScript.Echo 187:       Next 188: 189:       Set objWMIInstances = Nothing 190:    End If 191: ...: ...: ...: 

end example

This piece of code has one peculiarity, since it not only shows the properties of the Win32_PageFile instances (lines 127 and 130 through 153) but also shows the page file usage for the corresponding instance (lines 158 and 159 and 162 through 181). The page file usage is available from an instance of the Win32_PageFileUsage class. This class uses the same property key as the Win32_PageFile class. This is why, at lines 158 and 159, the Name property of the Win32_PageFile class is used. Because these two classes have some properties in common, the loop (lines 163 through 181) skips some of the properties to avoid duplicated information. The obtained output is as follows:

  1:    C:\>WMIPageFile.wsf /Action:List  2:    Microsoft (R) Windows Script Host Version 5.6  3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:    - J:\PAGEFILE.SYS------------------------------------------------------------  6:      Archive: ............................... TRUE  7:      Compressed: ............................ FALSE  8:      CreationDate: .......................... 28-11-2001 19:19:19  9:      CSName: ................................ NET-DPEN6400 10:      Drive: ................................. j: 11:      EightDotThreeFileName: ................. j:\pagefile.sys 12:      Encrypted: ............................. FALSE 13:      Extension: ............................. sys 14:      FileName: .............................. pagefile 15:      FileSize: .............................. 704643072 16:      FileType: .............................. System file 17:      FSName: ................................ NTFS 18:      Hidden: ................................ TRUE 19:      InitialSize: ........................... 672 20:      InstallDate: ........................... 28-11-2001 19:19:19 21:      LastAccessed: .......................... 10-02-2002 07:45:39 22:      LastModified: .......................... 10-02-2002 07:45:39 23:      MaximumSize: ........................... 1344 24:      Path: .................................. \ 25:      Readable: .............................. TRUE 26:      Status: ................................ OK 27:      System: ................................ TRUE 28:      Writeable: ............................. TRUE 29: 30:      CurrentUsage: .......................... 26 31:      PeakUsage: ............................. 27 

Sample 2.39: Creating page files (Part III)

start example

 ...: ...: ...: 191: 192:    ' -- CREATE ------------------------------------------------------------------------- 193:    If boolCreate = True Then 194:       Set objWMIClass = objWMIServices.Get (cWMIPageFileClass) ...: 197:       Set objWMIInstance = objWMIClass.SpawnInstance_ 198: 199:       objWMIInstance.Name = strWMIInstanceName 200: 201:       If boolInitialSize Then 202:          objWMIInstance.InitialSize = longInitialSize 203:       Else 204:          objWMIInstance.InitialSize = 0 205:       End If 206: 207:       If boolMaximumSize Then 208:          objWMIInstance.MaximumSize = longMaximumSize 209:       Else 210:          objWMIInstance.MaximumSize = 256 211:       End If 212: 213:       objWMIInstance.Put_ (wbemChangeFlagCreateOrUpdate Or wbemFlagReturnWhenComplete) 214:       If Err.Number Then ErrorHandler (Err) 215: 216:       WScript.Echo "Pagefile '" & Ucase (objWMIInstance.Name) & "' created (" & _ 217:                    longInitialSize & "/" & longMaximumSize & ")." ...: 220:    End If 221: ...: ...: ...: 

end example

Creating a new page file creates a new Win32_PageFile instance. This logic is exactly the same as that used to create new environment variables (see Sample 2.28). The script creates an instance of the class (line 194); next, it creates a new page file instance (line 197). Based on the parameters given on the command line, it initializes the properties of the new page file (lines 199 through 211). Once completed, the created instance is saved (line 213).

Sample 2.40: Updating page files (Part IV)

start example

 ...: ...: ...: 221: 222:    ' -- UPDATE ------------------------------------------------------------------------- 223:    If boolUpdate = True Then 224:       Set objWMIInstance = objWMIServices.Get (cWMIPageFileClass & "='" & _ 225:                                                strWMIInstanceName & "'") ...: 228:       If boolInitialSize Then 229:          WScript.Echo "Current initial size is " & objWMIInstance.InitialSize & " MB." 230:          objWMIInstance.InitialSize = longInitialSize 231:       End If 232: 233:       If boolMaximumSize Then 234:          WScript.Echo "Current maximum size is " & objWMIInstance.MaximumSize & " MB." 235:          objWMIInstance.MaximumSize = longMaximumSize 236:       End If 237: 238:       objWMIInstance.Put_ (wbemChangeFlagUpdateOnly Or wbemFlagReturnWhenComplete) 239:       If Err.Number Then ErrorHandler (Err) 240: 241:       WScript.Echo 242:       WScript.Echo "Pagefile '" & Ucase (objWMIInstance.Name) & "' updated (" & _ 243:                    longInitialSize & "/" & longMaximumSize & ")." 244: 245:       Set objWMIInstance = Nothing 246:    End If 247: ...: ...: ...: 

end example

To update page file settings, an instance of the page file is retrieved (lines 224 and 225). Once retrieved, the properties are initialized according to the parameters given on the command line (lines 228 through 236). Once modified, the changes are committed back (line 238). Notice the use of the wbemChangeFlagUpdateOnly flag to perform only an update operation. This code is very similar to that used to update an environment variable value (see Sample 2.29).

Sample 2.41: Deleting page files (Part V)

start example

 ...: ...: ...: 247: 248:    ' -- DELETE ------------------------------------------------------------------------- 249:    If boolDelete = True Then 250:       Set objWMIInstance = objWMIServices.Get (cWMIPageFileClass & "='" & _ 251:                                                strWMIInstanceName & "'") ...: 254:       objWMIInstance.Delete_ 255:       If Err.Number Then ErrorHandler (Err) 256: 257:       WScript.Echo "Pagefile '" & Ucase (objWMIInstance.Name) & "' deleted." 258: 259:       Set objWMIInstance = Nothing 260:    End If ...: 264:    ]]> 265:    </script> 266:  </job> 267:</package> 

end example

The last operation uses the same tactic as deleting an environment variable (see Sample 2.30); once the instance is retrieved (lines 250 and 251), the Delete_ method of the SWBemObject is executed to delete the page file instance (line 254).

2.4.6 Multimedia audio/visual class

This category contains only one class: the Win32_CodeFile class. This class has the same properties and methods as its parent class, the CIM_DataFile class (see Figure 2.12). There is only one new property defined at the level of the Win32_CodecFile class: the Group property. This Group property indicates the type of codec represented by the codec file instance. We can reuse the GetCollectionOfInstances.wsf sample developed previously (see Sample 1.5, "Listing all instances of a class with their properties formatted") to list the Win32_CodecFile instances.

   1:    C:\>GetCollectionOfInstances Win32_CodecFile   2:    Microsoft (R) Windows Script Host Version 5.6   3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.   4:   5:   6:    AccessMask: .............................. 18809343   7:    Archive: ................................. TRUE   8:    Caption: ................................. j:\windows\system32\msadp32.acm   9:    Compressed: .............................. FALSE  10:    CreationClassName: ....................... Win32_CodecFile  11:    CreationDate: ............................ 12-08-2001 21:29:10  12:    CSCreationClassName: ..................... Win32_ComputerSystem  13:    CSName: .................................. XP-DPEN6400  14:    Description: .............................  15:    Drive: ................................... j:  16:    EightDotThreeFileName: ................... j:\windows\system32\msadp32.acm  17:    Encrypted: ............................... FALSE  18:    Extension: ............................... acm  19:    FileName: ................................ msadp32  20:    FileSize: ................................ 13312  21:    FileType: ................................ acm File  22:    FSCreationClassName: ..................... Win32_FileSystem  23:    FSName: .................................. NTFS  24:    Group: ................................... Audio  25:    Hidden: .................................. FALSE  26:    InstallDate: ............................. 12-08-2001 21:29:10  27:    LastAccessed: ............................ 01-09-2001 17:25:23  28:    LastModified: ............................ 01-08-2001 16:00:00  29:    Manufacturer: ............................ Microsoft Corporation  30:    *Name: ................................... J:\WINDOWS\System32\MSADP32.ACM  31:    Path: .................................... \windows\system32\  32:    Readable: ................................ TRUE  33:    Status: .................................. OK  34:    System: .................................. FALSE  35:    Version: ................................. 5.1.3531.0 (main.010730-1811)  36:    Writeable: ............................... TRUE  37:  ..:  ..:  ..: 102:    AccessMask: .............................. 18809343 103:    Archive: ................................. TRUE 104:    Caption: ................................. j:\windows\system32\iccvid.dll 105:    Compressed: .............................. FALSE 106:    CreationClassName: ....................... Win32_CodecFile 107:    CreationDate: ............................ 12-08-2001 21:28:52 108:    CSCreationClassName: ..................... Win32_ComputerSystem 109:    CSName: .................................. XP-DPEN6400 110:    Description: ............................. 111:    Drive: ................................... j: 112:    EightDotThreeFileName: ................... j:\windows\system32\iccvid.dll 113:    Encrypted: ............................... FALSE 114:    Extension: ............................... dll 115:    FileName: ................................ iccvid 116:    FileSize: ................................ 110592 117:    FileType: ................................ Application Extension 118:    FSCreationClassName: ..................... Win32_FileSystem 119:    FSName: .................................. NTFS 120:    Group: ................................... Video ...: ...: ...: 

2.4.7 Networking classes

The networking category class represents network connections, network clients, and network connection settings. The classes included in this category are shown in Table 2.18.

Table 2.18: The Networking Classes

Name

Type

Description

Win32_IP4RouteTableEvent

Extrinsic event

Represents IP route change events.

Win32_IP4PersistedRouteTable

Dynami

Represents persisted IP routes.

Win32_IP4RouteTable

Dynami

Represents information that governs the routing of network data packets.

Win32_NetworkClient

Dynami

Represents a network client on a Windows system.

Win32_NetworkConnection

Dynami

Represents an active network connection in a Windows environment.

Win32_NetworkProtocol

Dynamic

Represents a protocol and its network characteristics on a Windows computer system.

Win32_NTDomain

Dynami

Represents a Windows NT domain.

Win32_PingStatus

Dynamic

Represents the values returned by the standard ping command.

Win32_ActiveRoute

Association

Relates the current IP4 route to the persisted IP route table.

Win32_ProtocolBinding

Association

Relates a system-level driver, network protocol, and network adapter.

Some of these classes are not supported by the Win32 providers. The Win32_ActiveRoute, Win32_IP4PersistedRouteTable, Win32_IP4RouteTable, and Win32_IP4RouteTableEvent classes are supported by the WMI RouteProvider provider. The Win32_PingStatus class is supported by the WMIPingProvider provider. Since the WMI RouteProvider and WMIPingProvider providers are discussed in the next chapter, we will not consider these classes in this section.

To retrieve information from the Win32_NetworkClient classes, we can reuse the GetCollectionOflnstances.wsf sample developed previously (see Sample 1.5, "Listing all instances of a class with their properties formatted") to list the properties of the Win32_NetworkClient class.

 C:\>GetCollectionOfInstances Win32_NetworkClient Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Caption: ................................. Workstation Description: ............................. Creates and maintains client network connections to                                            remote servers. If this service is stopped, these                                            connections will be unavailable. If this service is                                            disabled, any services that explicitly depend on it will                                            fail to start. Manufacturer: ............................ Microsoft Corporation *Name: ................................... Microsoft Windows Network Status: .................................. OK Caption: ................................. WebClient Description: ............................. Enables Windows-based programs to create, access, and                                            modify Internet-based files. If this service is stopped,                                            these functions will not be available. If this service is                                            disabled, any services that explicitly depend on it will                                            fail to start. Manufacturer: ............................ Microsoft Corporation *Name: ................................... Web Client Network Status: .................................. OK 

The Win32_NetworkConnection retrieves the list of the network connections made in the system. Basically, retrieving the Win32_NetworkConnection instances is similar to a "Net Use" command. Here is sample output of a Win32_Network Connection instance:

 C:\>GetCollectionOfInstances Win32_NetworkConnection Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Caption: ................................. RESOURCE CONNECTED Comment: ................................. ConnectionState: ......................... Connected ConnectionType: .......................... Current Connection Description: ............................. RESOURCE CONNECTED - Microsoft Windows Network DisplayType: ............................. Share LocalName: ............................... R: *Name: ................................... \\MyXPServer\MyShare (R:) Persistent: .............................. FALSE ProviderName: ............................ Microsoft Windows Network RemoteName: .............................. \\MyXPServer\MyShare RemotePath: .............................. \\MyXPServer\MyShare ResourceType: ............................ Disk Status: .................................. OK UserName: ................................ LISSWARENET\Alain.Lissoir 

The Win32_MappedLogicalDisk class retrieves information in a manner similar to the Win32_NetworkConnection class. However, the Win32_MappedLogicalDisk class is derived from the CIM_LogicalDisk superclass, such as the Win32_LogicalDisk. (See Figure 2.14.)


Figure 2.14: The CIM_LogicalDisk and its subclasses.

The information displayed by this class when a connection is made via the R: drive letter is as follows:

 C:\>GetCollectionOfInstances Win32_MappedLogicalDisk Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Caption: ................................. R: Compressed: .............................. FALSE *DeviceID: ............................... R: FileSystem: .............................. NTFS FreeSpace: ............................... 5447909376 InstallDate: ............................. 01-01-2000 MaximumComponentLength: .................. 255 Name: .................................... R: *SessionID: .............................. 115643 Size: .................................... 20398661632 SupportsDiskQuotas: ...................... FALSE SupportsFileBasedCompression: ............ TRUE SystemCreationClassName: ................. Win32_ComputerSystem SystemName: .............................. NET-DPEN6400 VolumeName: .............................. Shared VolumeSerialNumber: ...................... 0837A458 

The user-related information for this connection is not available from the class. However, the Win32_MappedLogicalDisk class is associated with the Win32_LogonSession (see Figure 2.15).

click to expand
Figure 2.15: The Win32_ MappedLogicalDisk class and its associations.

With the help of the Win32_LogonSession, it is possible to retrieve the user information, because this class is associated with the Win32_Account class, as shown in Figure 2.16.

click to expand
Figure 2.16: The Win32_LogonSession and its associations.

The Win32_NetworkProtocol class is used in Sample 2.8 ("Retrieving network device information [Part I]"). Sample 2.42 contains the previously skipped piece of code in Sample 2.8.

Sample 2.42: Retrieving network device information (Part V)

start example

 ...: ...: ...: 160: 161:              Set objWMIProtocolInstances = objWMIServices.ExecQuery _ 162:                                       ("Associators of {Win32_NetworkAdapter='" & _ 163:                                       objWMIAdapterInstance.Index & _ 164:                                       "'} Where ResultClass=Win32_NetworkProtocol") 165: 166:              If objWMIProtocolInstances.Count Then 167:                 For Each objWMIProtocolInstance In objWMIProtocolInstances 168:                     WScript.Echo 169:                     Set objWMIProperties = objWMIProtocolInstance.Properties_ 170:                     For Each objWMIProperty In objWMIProperties 171:                         DisplayFormattedProperty objWMIProtocolInstance, _ 172:                                                  objWMIProperty.Name, _ 173:                                                  objWMIProperty.Name, 174:                                                  Null 175:                     Next 176:                     Set objWMIProperties = Nothing 177:                 Next 178:              End If 179: ...: ...: ...: 

end example

With the association mechanism, the script retrieves the list of Win32_NetworkProtocol instances linked to the examined Win32_NetworkAdapter instance (lines 161 through 164). Figure 2.17 shows this relationship at the class level. Figure 2.2 shows the associations at the instance level.

click to expand
Figure 2.17: The Win32_NetworkAdapter class associations.

If the collection is not empty (line 166), the script displays the properties of each item. As a result, Sample 2.8 shows the complete set of information available from a Win32_NetworkAdapter instance. Note the presence of protocol drivers: MSAFD Tcpip [TCP/IP] from line 18 through 39 and MSAFD Tcpip [UDP/IP] from line 41 through 62.

  1:    C:\>"GetNetworkConfiguration (With NetProtocols).wsf" "Compaq NC3121 Fast Ethernet NIC"  2:    Microsoft (R) Windows Script Host Version 5.6  3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:    Adapter name: ............................ Compaq NC3121 Fast Ethernet NIC  6:    Device availability: ..................... Running/Full Power  7:    Adapter type: ............................ Ethernet 802.3  8:    Adapter state: ........................... Connected  9:    MAC address is : ......................... 00:08:C7:A9:27:56 10:    Adapter service name: .................... N100 11:    Last reset: .............................. 01-09-2001 18:02:30 12: 13:    *IRQ resource: ........................... 10 14:    Memory address: .......................... 0x40300000-0x40300FFF 15:    Memory address: .......................... 0x40100000-0x401FFFFF 16:    I/O Port: ................................ 0x00002420-0x0000243F 17: 18:    Caption: ................................. Tcpip 19:    ConnectionlessService: ................... FALSE 20:    Description: ............................. TCP/IP Protocol Driver 21:    GuaranteesDelivery: ...................... TRUE 22:    GuaranteesSequencing: .................... TRUE 23:    InstallDate: ............................. 12-08-2001 21:29:47 24:    MaximumAddressSize: ...................... 16 25:    MaximumMessageSize: ...................... 0 26:    MessageOriented: ......................... FALSE 27:    MinimumAddressSize: ...................... 16 28:    *Name: ................................... MSAFD Tcpip [TCP/IP] 29:    PseudoStreamOriented: .................... FALSE 30:    Status: .................................. OK 31:    SupportsBroadcasting: .................... FALSE 32:    SupportsConnectData: ..................... FALSE 33:    SupportsDisconnectData: .................. FALSE 34:    SupportsEncryption: ...................... FALSE 35:    SupportsExpeditedData: ................... TRUE 36:    SupportsGracefulClosing: ................. TRUE 37:    SupportsQuaranteedBandwidth: ............. FALSE 38:    SupportsMulticasting: .................... FALSE 39:    SupportsQualityofService: ................ FALSE 40: 41:    Caption: ................................. Tcpip 42:    ConnectionlessService: ................... TRUE 43:    Description: ............................. TCP/IP Protocol Driver 44:    GuaranteesDelivery: ...................... FALSE 45:    GuaranteesSequencing: .................... FALSE 46:    InstallDate: ............................. 12-08-2001 21:29:47 47:    MaximumAddressSize: ...................... 16 48:    MaximumMessageSize: ...................... 65467 49:    MessageOriented: ......................... TRUE 50:    MinimumAddressSize: ...................... 16 51:    *Name: ................................... MSAFD Tcpip [UDP/IP] 52:    PseudoStreamOriented: .................... FALSE 53:    Status: .................................. OK 54:    SupportsBroadcasting: .................... TRUE 55:    SupportsConnectData: ..................... FALSE 56:    SupportsDisconnectData: .................. FALSE 57:    SupportsEncryption: ...................... FALSE 58:    SupportsExpeditedData: ................... FALSE 59:    SupportsGracefulClosing: ................. FALSE 60:    SupportsGuaranteedBandwidth: ............. FALSE 61:    SupportsMulticasting: .................... TRUE 62:    SupportsQualityofService: ................ FALSE 63: 64:    DHCP enabled: ............................ FALSE 65:    IP address(es): .......................... 10.10.10.3 255.0.0.0 66:    IP connection metric: .................... 30 67:    Default Gateway(s) and metric: ........... 10.10.10.254 1 68:    Dead gateway detection enabled: .......... TRUE 69:    DNS registration enabled: ................ FALSE 70:    DNS FULL registration enabled: ........... TRUE 71:    DNS search order: ........................ 10.10.10.3 72:    DNS domain: .............................. LissWare.Net 73:    DNS enabled for WINS resolution: ......... FALSE 74:    WINS scope ID: ........................... 75:    Enable LMHOSTS lookup: ................... FALSE 76:    NETBIOS over TCP/IP: ..................... ENABLED 

The class to use to gather information about the Domain is the Win32_NTDomain class. Again, this class only displays information. The class does not offer methods or properties that can be changed. However, we will see later, with the Win32_ComputerSystem class, how to remove or join a domain from a Windows Server 2003 member server or a Windows XP client (currently, the Win32_ComputerSystem class under Windows 2000 does not contain any method to perform these operations). The property list obtained from the Win32_NTDomain class is as follows:

  1:    C:\>GetCollectionOfInstances Win32_NTDomain  2:    Microsoft (R) Windows Script Host Version 5.6  3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:  6:    Caption: ................................. LISSWARENET  7:    ClientSiteName: .......................... Brussels  8:    CreationClassName: ....................... Win32_NTDomain  9:    DcSiteName: .............................. Brussels 10:    Description: ............................. LISSWARENET 11:    DnsForestName: ........................... LissWare.Net 12:    DomainControllerAddress: ................. \\10.10.10.3 13:    DomainControllerAddressType: ............. 1 14:    DomainControllerName: .................... \\NET-DPEN6400 15:    DomainGuid: .............................. {CCA9C1AB-9500-4332-9237-EDEEA1057D46} 16:    DomainName: .............................. LISSWARENET 17:    DSDirectoryServiceFlag: .................. TRUE 18:    DSDnsControllerFlag: ..................... FALSE 19:    DSDnsDomainFlag: ......................... FALSE 20:    DSDnsForestFlag: ......................... TRUE 21:    DSGlobalCatalogFlag: ..................... TRUE 22:    DSKerberosDistributionCenterFlag: ........ TRUE 23:    DSPrimaryDomainControllerFlag: ........... TRUE 24:    DSTimeServiceFlag: ....................... FALSE 25:    DSWritableFlag: .......................... TRUE 26:    *Name: ................................... Domain: LISSWARENET 27:    Status: .................................. OK 

It is important to note some interesting information, such as the client (line 7) and Active Directory Domain Controller site location (line 9). Since the script runs on a Domain Controller, some extra information about the directory service is also available (lines 17 through 25). We see that the system is acting as a Directory Server (line 17), that the DC and the Domain name do not use a DNS name (lines 18 and 19), but the Forest does use a DNS name (line 20). The DC is a Global Catalog server, a Kerberos ticket distribution center, and a PDC for the Domain (lines 21 through 23). However, the system does not act as a Time Service provider (line 24). This output is obtained on a Windows Server 2003 acting as a Domain Controller. The output obtained on a Windows XP client is as follows:

  1:    C:\>GetCollectionOfInstances Win32_NTDomain  2:    Microsoft (R) Windows Script Host Version 5.6  3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:  6:    Caption: ................................. XP-PRO01  7:    CreationClassName: ....................... Win32_NTDomain  8:    Description: ............................. XP-PRO01  9:    *Name: ................................... Domain: XP-PRO01 10:    Status: .................................. Unknown 11: 12:    Caption: ................................. LISSWARENET 13:    ClientSiteName: .......................... Brussels 14:    CreationClassName: ....................... Win32_NTDomain 15:    DcSiteName: .............................. Brussels 16:    Description: ............................. LISSWARENET 17:    DnsForestName: ........................... LissWare.Net 18:    DomainControllerAddress: ................. \\10.10.10.3 19:    DomainControllerAddressType: ............. 1 20:    DomainControllerName: .................... \\XP-DPEN6400 21:    DomainGuid: .............................. {CCA9C1AB-9500-4332-9237-EDEEA1057D46} 22:    DomainName: .............................. LISSWARENET 23:    DSDirectoryServiceFlag: .................. TRUE 24:    DSDnsControllerFlag: ..................... FALSE 25:    DSDnsDomainFlag: ......................... FALSE 26:    DSDnsForestFlag: ......................... TRUE 27:    DSGlobalCatalogFlag: ..................... FALSE 28:    DSRerberosDistributionCenterFlag: ........ TRUE 29:    DSPrimaryDomainControllerFlag: ........... TRUE 30:    DSTimeServiceFlag: ....................... TRUE 31:    DSWritableFlag: .......................... TRUE 32:    *Name: ................................... Domain: LISSWARENET 33:    Status: .................................. OK 

2.4.8 Operating System settings classes

The operating system settings classes category represents the Operating System and its settings. This category class exposes an important number of settings that can be modified from a WMI script. The classes included in this category and supported by the Win32 WMI providers are listed in Table 2.19.

Table 2.19: The Operating System Settings Classes

Name

Type

Description

Win32_ComputerShutdownEvent

Extrinsic event

Represents computer shutdown events.

Win32_ComputerSystemEvent

Extrinsic event

Represents events related to a computer system.

Win32_DeviceChangeEvent

Extrinsic event

Represents device change events resulting from the addition, removal, or modification of devices on the computer system.

Win32_ModuleLoadTrace

Extrinsic event

Indicates that a process has loaded a new module.

Win32_ModuleTrace

Extrinsic event

Base event for module events.

Win32_ProcessStartTrace

Extrinsic event

Indicates that a new process has started.

Win32_ProcessStopTrace

Extrinsic event

Indicates that a process has terminated.

Win32_ProcessTrace

Extrinsic event

Base event for process events.

Win32_SystemConfigurationChangeEvent

Extrinsic event

Indicates that the device list on the system has been refreshed (a device has been added or removed, or the configuration changed).

Win32_SystemTrace

Extrinsic event

Base class for all system trace events, including module, process, and thread traces.

Win32_ThreadStartTrace

Extrinsic event

Indicates a new thread has started.

Win32_ThreadStopTrace

Extrinsic event

Indicates that a thread has stopped.

Win32_ThreadTrace

Extrinsic event

Base event class for thread events.

Win32_VolumeChangeEvent

Extrinsic event

Represents a network-mapped drive event resulting from the addition of a network drive letter or mounted drive on the computer system.

Win32_BootConfiguration

Dynamic

Represents the boot configuration of a Windows system.

Win32_ComputerSystem

Dynamic

Represents a computer system operating in a Windows environment

Win32_ComputerSystemProduct

Dynamic

Represents a product.

Win32_LoadOrderGroup

Dynamic

Represents a group of system services that define execution dependencies.

Win32_LoadOrderGroupServiceDependencies

Dynamic

Represents an association between a base service and a load order group that the service depends on to start running.

Win32_OperatingSystem

Dynamic

Represents an operating system installed on a Windows computer system.

Win32_OSRecoveryConfiguration

Dynamic

Represents the types of information that will be gathered from memory when the operating system fails.

Win32_QuickFixEngineering

Dynamic

Represents system-wide Quick Fix Engineering (QFE) or updates that have been applied to the current operating system.

Win32_StartupCommand

Dynamic

Represents a command that runs automatically when a user logs on to the computer system.

Win32_ComputerSystemProcessor

Association

Relates a computer system and a processor running on that system.

Win32_DependentService

Association

Relates two interdependent base services.

Win32_LoadOrderGroupServiceMembers

Association

Relates a load order group and a base service.

Win32_OperatingSystemQFE

Association

Relates an operating system and product updates applied as represented in Win32 QuickFixEngineering.

Win32_SystemBootConfiguration

Association

Relates a computer system and its boot configuration.

Win32_SystemDesktop

Association

Relates a computer system and its desktop configuration.

Win32_SystemDevices

Association

Relates a computer system and a logical device installed on that system.

Win32_SystemLoadOrderGroupss

Association

Relates a computer system and a load order group.

Win32_SystemNetworkConnections

Association

Relates a network connection and the computer system on which it resides.

Win32_SystemOperatingSystem

Association

Relates a computer system and its operating system.

Win32_SystemProcesses

Association

Relates a computer system and a process running on that system.

Win32_SystemProgramGroups

Association

Relates a computer system and a logial program group.

Win32_SystemResources

Association

Relates a system resource and the computer system it resides on.

Win32_SystemServices

Association

Relates a computer system and a service program that exists on the system.

Win32_SystemSetting

Association

Relates a computer system and a general setting on that system.

However, although related to the Operating System classes category, the extrinsic event classes listed in Table 2.19 are supported by a different set of WMI providers. We revisit these classes when examining the MS_Shutdown_Event_provider, WMI Kernel Trace Event provider, and SystemConfigurationChangeEvents WMI providers in the next chapter.

To customize the Operating System, it would be handy to have a script to configure the settings (dump file) and perform some typical Operating System operations (such as joining, unjoining a domain, renaming the computer, or rebooting the Operating System). This is the purpose of the next sample. For this, the script will make use of four classes. Each of them will be used for a specific set of tasks.

  • The Win32_ComputerSystem class: This class is used to gather information about the computer, to rename the computer, and to join and unjoin a domain or workgroup. With the same class, it is also possible to modify the time zone, daylight savings time, and the system startup options of the BOOT.INI file.

  • The Win32_QuickFixEngineering class: This class is used to retrieve the Quick Fix Engineering (QFE) installed in the Operating System.

  • The Win32_OperatingSystem class: This class is used to gather information about the Operating System, shut down the Operating System (shut down, reboot, or log off), change the date and time, or modify the foreground application time slice.

  • The Win32_OSRecoveryConfiguration class: This class is used to gather and set settings about system failure information, such as the auto reboot, the debug file path, the debug type desired, and if an Admin alert must be sent.

Before diving into the script code, let's see the command-line parameters exposed by this script sample:

 C:\>WMIOSConfig.wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIOSConfig.wsf [/List[+|-]] [/QFE[+|-]] [/Join:value] [/OU:value] [/UnJoin:value]                        [/Rename:value] [/AccountName:value] [/AccountPassword:value]                        [/SetDateTime:value] [/CurrentTimeZone:value]                        [/EnableDaylightSavingsTime[+|-]] [/SystemStartupDelay:value]                        [/SystemStartupOptions:value] [/SystemStartupSetting:value]                        [/ForegroundApplicationBoost:value] [/Shutdown:value] [/DebugFilePath:value]                        [/MiniDumpDirectory:value] [/DebugInfoType:value] [/AutoReboot[+|-]]                        [/OverwriteExistingDebugFile[+|-]] [/SendAdminAlert[+|-]]                        [/WriteToSystemLog[+|-]] [/Machine:value] [/User:value] [/Password:value] Options: List                       : View the Operating System configuration settings. QFE                        : View the Operating System Quick Fix Engineering. Join                       : Join computer systems to a domain or workgroup. OU                         : Distinguished name of the OU where the computer account must                              be created. UnJoin                     : Un-Join or removes a computer system from a domain or workgroup. Rename                     : Rename a computer. Must be local. AccountName                : Username to use for Join, Un-join or rename operation. Can be a UPN. AccountPassword            : Password for the Join, Un-join or rename operation. SetDateTime                : Set the date and time of the system CurrentTimeZone            : Set the system time zone. EnableDaylightSavingsTime  : Active the day light saving time. SystemStartupDelay         : Number of seconds to waut before booting. SystemStartupOptions       : Set options for starting the computer. SystemStartupSetting       : Set the index of the default start profile. ForegroundApplicationBoost : Increase the priority given to foreground applications. Must 0, 1 or 2. Shutdown                   : Must be [Shutdown], [Reboot], [Logoff] or [PowerOff]. DebugFilePath              : Indicates the path to the debug file. MiniDumpDirectory          : Indicates the directory where small memory dump files will be                              recorded and accumulated. DebugInfoType              : Indicates what type of debugging information is to be written saved.                              Must be [None], [Complete], [Kernel] or [Small]. AutoReboot                 : Determines whether the system will automatically reboot during a                              recovery operation. OverwriteExistingDebugFile : Indicates whether a new file will overwrite an existing one. SendAdminAlert             : Indicates whether or not an alert message will be sent to the system                              administrator. WriteToSystemLog           : Indicates whether or not events will be written to a system log. 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:       WMIOSConfig.wsf /List+       WMIOSConfig.wsf /QFE+       WMIOSConfig.wsf /Join:NewDomain /OU:OU=MyOU,DC=MyDomain,DC=Com                       /AccountName:Administrator /AccountPassword:password       WMIOSConfig.wsf /UnJoin+ /AccountName:Administrator /AccountPassword:password       WMIOSConfig.wsf /Rename:NewName /AccountName:Administrator /AccountPassword:password       WMIOSConfig.wsf /SetDateTime:20010901231500.000000+120       WMIOSConfig.wsf /CurrentTimeZone:120       WMIOSConfig.wsf /EnableDaylightSavingsTime+       WMIOSConfig.wsf /SystemStartupDelay:30       WMIOSConfig.wsf /SystemStartupOptions:"'Microsoft Windows Server 2003, Enterprise' /fastdetect"       WMIOSConfig.wsf /SystemStartupSetting:0       WMIOSConfig.wsf /ForegroundApplicationBoost:1       WMIOSConfig.wsf /Shutdown:Reboot       WMIOSConfig.wsf /DebugFilePath:%SystemRoot%\MEMORY.DMP       WMIOSConfig.wsf /MiniDumpDirectory:%SystemRoot%\Minidump       WMIOSConfig.wsf /DebugInfoType:Small       WMIOSConfig.wsf /AutoReboot+       WMIOSConfig.wsf /OverwriteExistingDebugFile+       WMIOSConfig.wsf /SendAdminAlert+       WMIOSConfig.wsf /WriteToSystemLog+ 

This script, along with Sample 2.12 ("Configuring a network adapter"), exposes a huge number of parameters. Since the command-line parameters analysis uses the same functions and techniques as Sample 2.12, we do not examine this part of the code. Sample 2.43 is structured in the same way as before: an XML section to define the XML named parameters (skipped from line 13 through 78) and a code section to parse and format the command-line parameters (skipped from line 114 through 340).

Sample 2.43: Configuring the Operating System (Part I)

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  78:    </runtime>  79:  80:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\ConvertStringInArrayFunction.vbs" />  81:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\ReplaceByFunction.vbs" />  82:  83:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" />  84:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  85:  86:    <object prog  reference="true"/>  87:    <object prog  />  88:  89:    <object prog  />  90:  91:    <script language="VBscript">  92:    <![CDATA[  ..:  96:    Const cComputerName = "LocalHost"  97:    Const cWMINameSpace = "root/cimv2"  98:  99:    Const cWMIComputerSysClass = "Win32_ComputerSystem" 100:    Const cWMIOperaringSystemClass = "Win32_OperatingSystem" 101:    Const cWMIOSRecoveryConfigClass = "Win32_OSRecoveryConfiguration" 102:    Const cWMIQFEClass = "Win32_QuickFixEngineering" 103: 104:    Const cLogOff = 1 105:    Const cShutdown = 2 106:    Const cReboot = 3 107:    Const cPowerOff = 9 108:    Const cForcedLogOff = 5 109:    Const cForcedShutdown = 6 110:    Const cForcedReboot = 7 111:    Const cForcedPowerOff = 13 112: 113:    Const cJoinOptions = 39     ' Bit 0=On, 1=On, 2=On and 5=On 114:    Const cUnJoinOptions = 4    ' Bit 2=On ...: ...: ...: 333:    strUserID = WScript.Arguments.Named("User") 334:    If Len(strUserID) = 0 Then strUserID = "" 335: 336:    strPassword = WScript.Arguments.Named("Password") 337:    If Len(strPassword) = 0 Then strPassword = "" 338: 339:    strComputerName = WScript.Arguments.Named("Machine") 340:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 341: 342:    objWMILocator.Security_.AuthenticationLevel = WbemAuthenticationLevelPktPrivacy 343:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 344:    objWMILocator.Security_.Privileges.AddAsString "SeSystemtimePrivilege", True 345:    objWMILocator.Security_.Privileges.AddAsString "SeRemoteShutdownPrivilege", True 346:    objWMILocator.Security_.Privileges.AddAsString "SeShutdownPrivilege", True 347: 348:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 349:                                                     strUserID, strPassword) ...: 352:    Set objWMIComputerSysInstances = objWMIServices.InstancesOf (cWMIComputerSysClass) ...: 355:    Set objWMIOSInstances = objWMIServices.InstancesOf (cWMIOperaringSystemClass) ...: 358:    Set objWMIOSRecConfigInstances = objWMIServices.InstancesOf (cWMIOSRecoveryConfigClass) ...: 360: ...: ...: ...: 

end example

When the WMI connection is established, some required privileges are granted to change the system time (line 344) and reboot the computer (lines 345 and 346). Without these privileges, it is impossible to successfully execute these operations. Of course, it is always possible to add some logic to specify these rights if only the corresponding switches are given on the command line. Next, three collections of instances from the Win32_ComputerSystem (line 352), Win32_OperatingSystem (line 355), and Win32_OSRecoveryConfiguration (line 358) classes are created. The Win32_ QuickFixEngineering class is used later. Notice in the script header, the definition of some constants (lines 104 through 114). These constants are used later to perform some specific WMI Operating System operations. We revisit this later during the script analysis.

The first step consists of viewing all properties of the three collections of instances just created. This action corresponds to the /List+ switch usage. The operation is executed in Sample 2.44 by performing an enumeration of the three collections: the Win32_ComputerSystem collection (lines 363 through 373), Win32_OperatingSystem collection (lines 378 through 388), and Win32_OSRecoveryConfiguration collection (lines 393 through 403).

Sample 2.44: Viewing various Operating System properties (Part II)

start example

 ...: ...: ...: 360: 361:    If boolList Then 362:       If objWMIComputerSysInstances.Count = 1 Then 363:          For Each objWMIComputerSysInstance in objWMIComputerSysInstances 364:              WScript.Echo "- Computer System " & String (60, "-") 365:              Set objWMIPropertySet = objWMIComputerSysInstance.Properties_ 366:              For Each objWMIProperty In objWMIPropertySet 367:                  DisplayFormattedProperty objWMIComputerSysInstance, _ 368:                                           objWMIProperty.Name, _ 369:                                           objWMIProperty.Name, _ 370:                                           Null 371:              Next 372:              Set objWMIPropertySet = Nothing 373:          Next 374:          WScript.Echo 375:       End If 376: 377:       If objWMIOSInstances.Count = 1 Then 378:          For Each objWMIOSInstance in objWMIOSInstances 379:              WScript.Echo "- OS Settings " & String (60, "-") 380:              Set objWMIPropertySet = objWMIOSInstance.Properties_ 381:              For Each objWMIProperty In objWMIPropertySet 382:                  DisplayFormattedProperty objWMIOSInstance, _ 383:                                           objWMIProperty.Name, _ 384:                                           objWMIProperty.Name, _ 385:                                           Null 386:              Next 387:              Set objWMIPropertySet = Nothing 388:          Next 389:          WScript.Echo 390:       End If 391: 392:       If objWMIOSRecConfigInstances.Count = 1 Then 393:         For Each objWMIOSRecConfigInstance in objWMIOSRecConfigInstances 394:             WScript.Echo "- OS Recovery Settings " & String (60, "-") 395:             Set objWMIPropertySet = objWMIOSRecConfigInstance.Properties_ 396:          For Each objWMIProperty In objWMIPropertySet 397:              DisplayFormattedProperty objWMIOSRecConfigInstance, _ 398:                                       objWMIProperty.Name, _ 399:                                       objWMIProperty.Name, _ 400:                                       Null 401:              Next 402:              Set objWMIPropertySet = Nothing 403:          Next 404:          WScript.Echo 405:       End If 406:    ElseIf boolQFE Then ...: ...: ...: 

end example

These three classes provide a rich set of information about the Operating System. Take a few minutes to review the listed properties with WMI CIM Studio.

The display output is given in the following code segment as reference. Information such as the domain role (line 18 and Table 2.20), infrared support capability (line 20), service pack level (line 63), and available memory (lines 50 and 98) are just a few examples.

Table 2.20: The DomainRole property of the Win32_ComputerSystem Class

Value

Description

0

Standalone Workstation

1

Member Workstation

2

Standalone Server

3

Member Server

4

Backup Domain Controller

5

Primary Domain Controller

   1:    C:\>WMIOSConfig.wsf /List+ /Machine:MyPortable /User:Administrator /Password:password   2:    Microsoft (R) Windows Script Host Version 5.6   3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.   4:   5:    - Computer System ------------------------------------------------------------   6:    AdminPasswordStatus: ......... 0   7:    AutomaticResetBootOption: .... TRUE   8:    AutomaticResetCapability: .... TRUE   9:    BootROMSupported: ............ TRUE  10:    BootupState: ................. Normal  11:    Caption: ..................... MYPORTABLE  12:    ChassisBootupState: .......... 3  13:    CreationClassName: ........... Win32_ComputerSystem  14:    CurrentTimeZone: ............. 60  15:    DaylightInEffect: ............ FALSE  16:    Description: ................. AT/AT COMPATIBLE  17:    Domain: ...................... WORKGROUP  18:    DomainRole: .................. 0  19:    FrontPanelResetStatus: ....... 2  20:    InfraredSupported: ........... TRUE  21:    KeyboardPasswordStatus: ...... 0  22:    Manufacturer: ................ Compaq  23:    Model: ....................... Armada M700  24:    *Name: ....................... MYPORTABLE  25:    NetworkServerModeEnabled: .... TRUE  26:    NumberOfProcessors: .......... 1  27:    OEMStringArray: .............. www.compaq.com  28:    PauseAfterReset: ............. -1  29:    PowerOnPasswordStatus: ....... 0  30:    PowerState: .................. 0  31:    PowerSupplyState: ............ 3  32:    PrimaryOwnerName: ............ Alain Lissoir  33:    ResetCapability: ............. 1  34:    ResetCount: .................. -1  35:    ResetLimit: .................. -1  36:    Roles: ....................... LM_Workstation  37:                                   LM_Server  38:                                   NT  39:                                   Potential_Browser  40:                                   Master_Browser  41:    Status: ...................... OK  42:    SystemStartupDelay: .......... 30  43:    SystemStartupOptions: ........ "Microsoft Windows 2000 Professional" /fastdetect  44:                                   "Microsoft Windows 2000 Advanced Server (LABS)" /fastdetect  45:                                   "Microsoft Windows Server 2003 Advanced Server (LABS)" /fastdetect  46:                                   "Windows NT Workstation Version 4.00 (Recovery)"  47:    SystemStartupSetting: ........ 0  48:    SystemType: .................. X86-based PC  49:    ThermalState: ................ 3  50:    TotalPhysicalMemory: ......... 267894784  51:    UserName: .................... MYPORTABLE\Lissoir  52:    WakeUpType: .................. 6  53:  54:    - OS Settings ------------------------------------------------  55:    BootDevice: .................. \Device\Harddisk0\Partition1  56:    BuildNumber: ................. 2195  57:    BuildType: ................... Uniprocessor Free  58:    Caption: ..................... Microsoft Windows 2000 Professional  59:    CodeSet: ..................... 1252  60:    CountryCode: ................. 1  61:    CreationClassName: ........... Win32_OperatingSystem  62:    CSCreationClassName: ......... Win32_ComputerSystem  63:    CSDVersion: .................. Service Pack 2  64:    CSName: ...................... MYPORTABLE  65:    CurrentTimeZone: ............. 60  66:    Debug: ....................... FALSE  67:    Description: .................  68:    Distributed: ................. FALSE  69:    ForegroundApplicationBoost: .. 2  70:    FreePhysicalMemory: .......... 86996  71:    FreeSpaceInPagingFiles: ...... 281828  72:    FreeVirtualMemory: ........... 368824  73:    InstallDate: ................. 01-01-1999 07:49:30  74:    LastBootUpTime: .............. 28-10-2001 15:28:20  75:    LocalDateTime: ............... 29-10-2001 14:48:27  76:    Locale: ...................... 0409  77:    Manufacturer: ................ Microsoft Corporation  78:    MaxNumberOfProcesses: ........ -1  79:    MaxProcessMemorySize: ........ 2097024  80:    *Name: ....................... Microsoft Windows 2000 Professional|C:\WINNT|\Devic...  81:    NumberOfProcesses: ........... 48   82:    NumberOfUsers: ............... 1  83:    Organization: ................ Compaq Computer  84:    OSLanguage: .................. 1033  85:    OSType: ...................... 18  86:    Primary: ..................... TRUE  87:    QuantumLength: ............... 0  88:    QuantumType: ................. 0  89:    RegisteredUser: .............. Alain Lissoir  90:    SerialNumber: ................ 51873-005-0246414-09900  91:    ServicePackMajorVersion: ..... 2  92:    ServicePackMinorVersion: ..... 0  93:    SizeStoredInPagingFiles: ..... 435704  94:    Status: ...................... OK  95:    SystemDevice: ................ \Device\Harddisk0\Partition1  96:    SystemDirectory: ............. C:\WINNT\System32  97:    TotalVirtualMemorySize: ...... 697320  98:    TotalVisibleMemorySize: ...... 261616  99:    Version: ..................... 5.0.2195 100:    WindowsDirectory: ............ C:\WINNT 101: 102:    - OS Recovery Settings ------------------------------------------------ 103:    AutoReboot: .................. TRUE 104:    DebugFilePath: ............... C:\WINNT\MEMORY.DMP 105:    KernelDumpOnly: .............. FALSE 106:    *Name: ....................... Microsoft Windows 2000 Professional|C:\WINNT|\Device\Hard... 107:    OverwriteExistingDebugFile: .. TRUE 108:    SendAdminAlert: .............. TRUE 109:    WriteDebugInfo: .............. FALSE 110:    WriteToSystemLog: ............ TRUE 

Listing the Quick Fix Engineering (QFE) is not complicated. The logic is always the same. The code is shown in Sample 2.45. A collection of the QFE instances is created (line 407); next, an enumeration of the collection is performed (lines 411 through 420).

Sample 2.45: Viewing Operating System QFE (Part III)

start example

 ...: ...: ...: 406:    ElseIf boolQFE Then 407:       Set objWMIQFEInstances = objWMIServices.InstancesOf (cWMIQFEClass) ...: 410:       If objWMIComputerSysInstances.Count = 1 Then 411:          For Each objWMIQFEInstance in objWMIQFEInstances 412:              WScript.Echo "- Quick Fix Engineering" & " (" & _ 413:                           objWMIQFEInstance.HotFixID & ") " & String (60, "-") 414:              Set objWMIPropertySet = objWMIQFEInstance.Properties_ 415:              For Each objWMIProperty In objWMIPropertySet 416:                  DisplayFormattedProperty objWMIQFEInstance, _ 417:                                           objWMIProperty.Name, _ 418:                                           objWMIProperty.Name, _ 419:                                           Null 420:              Next 421:              Set objWMIPropertySet = Nothing 422:              WScript.Echo 423:          Next 424:       End If ...: 427:    Else ...: ...: ...: 

end example

The next parts of the script are the most interesting ones because this is where some Operating System operations are executed. We start with the Win32_ComputerSystem class operations. With this class, it is possible to join or unjoin a domain or a workgroup. Moreover, the computer can also be renamed. Note that under Windows 2000 and before, it is only possible to rename the computer. The WMI implementation under Windows 2000 and before does not contain a Win32_ComputerSystem class definition that exposes a method to join and unjoin from a domain or a workgroup. Sample 2.46 shows how to proceed.

Sample 2.46: Joining and unjoining a domain or workgroup, and renaming a workstation (Part IV)

start example

 ...: ...: ...: 427:    Else 428:       If objWMIComputerSysInstances.Count = 1 Then 429:          For Each objWMIComputerSysInstance in objWMIComputerSysInstances 430:              If Len(strJoin) Then 431:                 intRC = objWMIComputerSysInstance.JoinDomainOrWorkGroup (strJoin, _ 432:                                                                          strAccountPassword, _ 433:                                                                          strAccountName, _ 434:                                                                          strJoinOU, _ 435:                                                                          cJoinOptions) 436:                 WScript.Echo "Join completed (" & intRC & ")." 437:              End If 438: 439:              If boolUnJoin Then 440:                 intRC = objWMIComputerSysInstance.UnJoinDomainOrWorkGroup (strAccountPassword, 441:                                                                           strAccountName, _ 442:                                                                           cUnJoinOptions) 443:                 WScript.Echo "UnJoin completed (" & intRC & ")." 444:              End If 445: 446:              If Len(strRename) Then 447:                 intRC = objWMIComputerSysInstance.Rename (strRename, _ 448:                                                           strAccountPassword, _ 449:                                                           strAccountName) 450:                 WScript.Echo "Rename completed (" & intRC & ")." 451:              End If 452: 453: ...: ...: ...: 

end example

If the /Join switch, for example, is specified with a domain name to join, lines 430 through 437 are executed. The JoinDomainOrWorkGroup method of the Win32_ComputerSystem instance accepts five parameters. The first parameter is the domain or workgroup name to join and is contained in the strJoin variable (line 431). Because joining a domain or workgroup can't usually be made without specific credentials, the next two parameters are the account name and the password to use (lines 432 and 433). During the join operation, a computer object can be created (based on the flags given in the last parameter). If the computer account is created, it can be created in a specific OU of Active Directory. This fourth parameter contains the distinguishedName of the OU targeted for the computer account creation. If the default container must be used, this parameter must be set to Null. Last, but not least, the fifth parameter is the join options parameter. It contains a set of bit flags defining the join options. The bit flag meaning is shown in Table 2.21.

Table 2.21: The Join and Unjoin Options

Join options

Bit

Action

Description

0

Join Domain

If set (value=1), it joins the computer to a domain. If this bit flag equals 0, it joins the computer to a workgroup.

2

Acct Delete

If set (value=4), it deletes the account when a domain is left.

4

Win9X Upgrade

If set (value=16), the join operation is occurring as part of an upgrade of Windows 95/98 to Windows NT/Windows 2000.

5

Domain join if already joined

If set (value=32), it allows a join to a new domain even if the computer is already joined to a domain.

6

Join unsecure

If set (value=64), it performs an unsecured join.

7

Machine password passed

If set (value=128), it indicates that the machine (not user) password is passed. This option is only valid for unsecure joins.

8

Deferred SPN Set

If set (value=256), it specifies that writing service principal name (SPN) and DnsHostName attributes on the computer object should be deferred until the rename that will follow the join.

18

Install Invocation

If set (value=262144), the APIs were invoked during install.

Unjoin options

Bit

Action

Description

2

Acct Delete

If set (value=4), it deletes the computer account when a domain is left. Actually, the account is disabled when the unjoin occurs.

In the script header, at line 113, a constant called cJoinOptions is defined with a value equal to 39. This value corresponds to the bit flags 0, 1, 2, and 5 set to 1 (1 + 2 + 4 + 32 = 39). This default value is used by the script at line 435 and corresponds to the most suitable value to use for the script purpose. Based on the script context usage (i.e., during an upgrade to Windows XP), it is necessary to adapt the value. Once the method is executed, it returns a 0 if the join is successful (line 436).

If the /Unjoin+ switch is specified, lines 439 through 444 are executed. The UnJoinDomainOrWorkGroup method of the Win32_ComputerSystem instance accepts three parameters: the account with the password for the unjoin operation (lines 440 and 441) and the unjoin options parameter (line 442) defined at line 114 of Sample 2.43. The unjoin is made up of one bit flag, listed in Table 2.21. Once the method executes, it returns a 0 if the unjoin is successful (line 443). When bit 2 is set to ON (Value = 4), the unjoined domain must be reachable, since the computer account is disabled. If the domain you quit is not available anymore, ensure that bit 2 is OFF (Value = 0); otherwise, you won't be able to leave the domain.

If the /Rename switch is specified with the new computer name, lines 446 through 451 are executed. The Rename method of the Win32_ComputerSystem instance accepts three parameters: the new computer name (line 447) and the account with the password for the rename operation (lines 447 and 448). Once the method executes, it returns a 0 if the rename is successful (line 443). However, the computer must be rebooted to get the new name in effect. We see later, in the same script, how to reboot the computer.

The next piece of code, presented in Sample 2.47, modifies some properties of the Win32_ComputerSystem instance.

Sample 2.47: Time zone, daylight savings, and startup options (Part V)

start example

 ...: ...: ...: 453:              If intCurrentTimeZone <> - 1 Then 454:                 objWMIComputerSysInstance.CurrentTimeZone = intCurrentTimeZone 455:                 WScript.Echo "CurrentTimeZone set." 456:              End If 457: 458:              If Len (boolDaylightSavingsTime) Then 459:                 objWMIComputerSysInstance.EnableDaylightSavingsTime = boolDaylightSavingsTime 460:                 If boolDaylightSavingsTime Then 461:                    WScript.Echo "EnableDaylightSavingsTime set." 462:                 Else 463:                    WScript.Echo "EnableDaylightSavingsTime unset." 464:                 End If 465:              End If 466: 467:              If intSysStartupDelay <> -1 Then 468:                 objWMIComputerSysInstance.SystemStartupDelay = intSysStartupDelay 469:                 WScript.Echo "SystemStartupDelay set." 470:              End If 471: 472:              If IsArray (arraySysStartupOptions) Then 473:                 objWMIComputerSysInstance.SystemStartupOptions = arraySysStartupOptions 474:                 WScript.Echo "SystemStartupOptions set." 475:              End If 476: 477:              If intSysStartupSetting <> - 1 Then 478:                 objWMIComputerSysInstance.SystemStartupSetting = intSysStartupSetting 479:                 WScript.Echo "SystemStartupSetting set." 480:              End If 481: 482:              objWMIComputerSysInstance.Put_ (wbemChangeFlagUpdateOnly Or _ 483:                                              wbemFlagReturnWhenComplete) 484:              If Err.Number Then ErrorHandler (Err) 485:          Next 486:       End If 487: ...: ...: ...: 

end example

This piece of code modifies the computer time zone, as well as the daylight savings time and the startup options. The computer time zone is a boundary value of 60 and comprised between -720 and +780 (lines 453 through 456). For daylight savings time, it is a Boolean value set on True to enable daylight savings time (lines 458 through 465).

The rest of the code (from line 467) changes the system startup parameters encoded in the Boot.Ini file. If we consider the following Boot.INI:

 [boot loader] timeout=30 default=multi(0)disk(0)rdisk(0)partition(2)\WINDOWS [operating systems] multi(0)disk(0)rdisk(0)partition(2)\WINDOWS="MS Windows 2003 " /fastdetect multi(0)disk(0)rdisk(1)partition(2)\WINDOWS="MS Windows XP" /fastdetect 

If the switch:

 /SystemStartupDelay:120 

is used, the timeout parameter of the Boot.Ini is set to 120 seconds. However, when changing the other two startup options, some care must be taken. As we can see in the code at line 473, the SystemStartupOptions property accepts an array to specify the startup options. The array only contains the assigned information to the partition pointers, which are:

 "MS Windows 2003" /fastdetect "MS Windows XP" /fastdetect 

It is important to respect the order of the items in the array. In the Boot.INI sample, the line defining the Windows Server 2003 boot partition is the first one, while the second line defines the Windows XP boot partition. This means that to respect the Boot.INI items ordering, while updating it, element 0 of the array must contain:

 "MS Windows Server 2003" /fastdetect /debug 

while element 1 of the array must contain:

 "MS Windows XP" /fastdetect /debug 

If the elements 0 and 1 are inverted in the array, this will result in an incorrect assignment of the partition pointers. In such a case, the Boot.Ini will look like:

 [boot loader] timeout=30 default=multi(0)disk(0)rdisk(0)partition(2)\WINDOWS [operating systems] multi(0)disk(0)rdisk(0)partition(2)\WINDOWS="MS Windows XP" /fastdetect /debug multi(0)disk(0)rdisk(1)partition(2)\WINDOWS="MS Windows Server 2003" /fastdetect /debug 

which is obviously wrong since the multi(0)disk(0)rdisk(0)partition(2)\WINDOWS partition physically contains the Windows Server 2003 and the multi(0)disk(0)rdisk(1)partition(2)\WINDOWS partition physically contains Windows XP. Although not a disaster, this may introduce some confusion when manipulating the startup options.

Because this information contains some double quotes, which can cause some trouble when specified from the command line, the script accepts single quotes from the command line and converts them into double quotes before assignment (during the command-line parameters parsing). This is the reason why the function ReplaceBy() is included at the beginning of the script in Sample 2.43 (line 81). So, the command line for this switch must look like:

 WMIOSConfig.wsf /SystemStartupOptions:"'MS Windows Server 2003' /fastdetect,'MS Windows XP' /fastdetect" 

Note the order of the items to match Boot.INI items' ordering and the use of the comma to separate each item in the array. The last startup option is modified with the /SystemStartupSetting switch (lines 477 through 480). This parameter is an index that corresponds to the items ordering in the Boot.INI file. If the startup options must be set to boot Windows Server 2003 by default, the following command line will be used (based on the original Boot.INI):

 WMIOSConfig.wsf /SystemStartupSetting:0 

If Windows XP must be booted by default, the following command line must be used:

 WMIOSConfig.wsf /SystemStartupSetting:1 

The use of the startup options implies knowledge of the item ordering in the Boot.INI. This is very important in order to modify the Boot.INI correctly. To commit the changes, the Put_ method of the SWBemObject object (which contains the Win32_ComputerSystem instance) is invoked (lines 482 and 483).

The next piece of code modifies some more Operating System parameters with the help of the Win32_OSRecoveryConfiguration class.

Sample 2.48: The Operating System recovery parameters (Part VI)

start example

 ...: ...: ...: 487: 488:       If objWMIOSRecConfigInstances.Count = 1 Then 489:          For Each objWMIOSRecConfigInstance in objWMIOSRecConfigInstances 490:              If Len (strDebugFilePath) Then 491:              objWMIOSRecConfigInstance.DebugFilePath = strDebugFilePath 492:              objWMIOSRecConfigInstance.ExpandedDebugFilePath = strExpDebugFilePath 493:              WScript.Echo "DebugFilePath set." 494:           End If 495: 496:           If Len (strMiniDumpDirectory) Then 497:              objWMIOSRecConfigInstance.MiniDumpDirectory = strMiniDumpDirectory 498:              objWMIOSRecConfigInstance.ExpandedMiniDumpDirectory = strExpMiniDumpDirectory 499:              WScript.Echo "MiniDumpDirectory set." 500:           End If 501: 502:           If intDebugInfoType Then 503:              objWMIOSRecConfigInstance.DebugInfoType = intDebugInfoType - 1 504:              WScript.Echo "DebugInfoType set." 505:           End If 506: 507:           If Len (boolAutoReboot) Then 508:              objWMIOSRecConfigInstance.AutoReboot = boolAutoReboot 509:              If boolAutoReboot Then 510:                 WScript.Echo "AutoReboot set." 511:              Else 512:                 WScript.Echo "AutoReboot unset." 513:              End If 514:           End If 515: 516:           If Len (boolOverwriteDebugFile) Then 517:              objWMIOSRecConfigInstance.OverwriteExistingDebugFile = boolOverwriteDebugFile 518:              If boolOverwriteDebugFile Then 519:                 WScript.Echo "OverwriteExistingDebugFile set." 520:              Else 521:                 WScript.Echo "OverwriteExistingDebugFile unset." 522:              End If 523:           End If 524: 525:           If Len (boolSendAdminAlert) Then 526:              objWMIOSRecConfigInstance.SendAdminAlert = boolSendAdminAlert 527:              If boolSendAdminAlert Then 528:                 WScript.Echo "SendAdminAlert set." 529:              Else 530:                 WScript.Echo "SendAdminAlert unset." 531:              End If 532:           End If 533: 534:           If Len (boolWriteToSystemLog) Then 535:              objWMIOSRecConfigInstance.WriteToSystemLog = boolWriteToSystemLog 536:              If boolWriteToSystemLog Then 537:                 WScript.Echo "WriteToSystemLog set." 538:              Else 539:                 WScript.Echo "WriteToSystemLog unset." 540:              End If 541:           End If 542: 543:           objWMIOSRecConfigInstance.Put_ (wbemChangeFlagUpdateOnly Or _ 544:                                           wbemFlagReturnWhenComplete) 545:           If Err.Number Then ErrorHandler (Err) 546:       Next 547:    End If 548: ...: ...: ...: 

end example

The change of the Operating System recovery options is pretty easy and does not contain any tricks. Each property is assigned with the value specified from the command line. For instance, from line 490 through 494, the debugging file path is set, and from line 496 through 500, the minidump directory is set. Lines 502 through 505 assign a value that corresponds to the dump type desired. The values and the corresponding dump type are presented in Table 2.22.

Table 2.22: The Operating System File Dump Values

Value

Description

0

None

1

Complete

2

Kernel

3

Small

The changes are committed with the Put_ method of the SWBemObject object, which contains the Win32_OSRecoveryConfiguration instance (lines 543 and 544).

The last piece of code concerning the Operating System operations is shown in Sample 2.49 and modifies the application time slice, the system date and time, and also can reboot the computer.

Sample 2.49: Setting application time slice, date and time, and rebooting the Operating System (Part VII)

start example

 ...: ...: ...: 548: 549:       If objWMIOSInstances.Count = 1 Then 550:          For Each objWMIOSInstance in objWMIOSInstances 551: 552:              If intForeAppsBoost <> - 1 Then 553:                 objWMIOSInstance.ForegroundApplicationBoost = intForeAppsBoost 554:                 WScript.Echo "ForegroundApplicationBoost set." 555:              End If 556: 557:              If Len (strDateTime) Then 558:                 intRC = objWMIOSInstance.SetDateTime (strDateTime) 559:                 WScript.Echo "SetDateTime (" & intRC & ")." 560:              End If 561: 562:              If intShutdownValue Then 563:                 intRC = objWMIOSInstance.Win32Shutdown (intShutdownValue - 1) 564:                 WScript.Echo "Shutdown (" & intRC & ")." 565:              End If 566: 567:              objWMIOSInstance.Put_ (wbemChangeFlagUpdateOnly Or _ 568:                                     wbemFlagReturnWhenComplete) 569:              If Err.Number Then ErrorHandler (Err) 570:          Next 571:       End If 572:    End If ...: 580:    ]]> 581:    </script> 582:  </job> 583:</package> 

end example

When the /ForegroundApplicationBoost switch is used with a value between 0 and 2, it modifies the priority given to the foreground application (lines 552 through 555). On computer systems running Windows NT 4.0 and Windows 2000 and beyond, application boost is implemented by giving an application more execution time slices, called the quantum lengths. A value of 0 boosts the quantum length by 6. If the value is set to 1, the system boosts the quantum length by 12, and if set to 2, the system boosts the quantum by 18. The default value is 2. On Windows NT 3.51 and earlier, application boost is implemented by increasing the scheduling priority. For these systems, the scheduling priority is increased by the value of this property.

To change the date and time of the computer, the /SetDateTime switch must be used with one parameter that contains a date and time value in DMTF format. Once specified, lines 557 through 560 are executed.

To reboot the computer, the script uses the Win32Shutdown method of the Win32_OperatingSystem instance (lines 562 through 565). This method accepts one parameter, which contains a set of bit flags. Table 2.23 contains the different values with their corresponding actions.

Table 2.23: The Operating System Shutdown Values

Value

Description

0

Log Off

0 + 4

Forced Log Off

1

Shutdown

1 + 4

Forced Shutdown

2

Reboot

2 + 4

Forced Reboot

8

Power Off

8 + 4

Forced Power Off

The script header contains some constants (see Sample 2.43, from line 104 through 110) that define the miscellaneous values. The command-line parsing converts the command-line keyword to the corresponding value passed to the Win32Shutdown method. For instance, to reboot a computer with the script, the following command line must be used:

 WMIOSConfig.wsf /Shutdown:Reboot 

To shut down the computer, the following command line must be used:

 WMIOSConfig.wsf /Shutdown:Shutdown 

2.4.9 Process classes

The process category classes represent the system processes and threads. The classes supported by the Win32 providers and included in this category are listed in Table 2.24.

Table 2.24: The Process Classes

Name

Description

Win32_Process

Represents a sequence of events on a Windows system.

Win32_ProcessStartup

Represents the startup configuration of a Windows process.

Win32_Thread

Represents a thread of execution.

These classes are not the only classes referring to the processes. For instance, the Win32_NamedJobObject class also provides some information about the processes. We revisit the Job Kernel-related classes when examining the Job Kernel providers in the next chapter.

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. Only the job objects that have been named are instrumented.

With the Win32_Process class, it is possible to gather information about the running processes, create new processes, and kill processes. The next script sample performs these tasks. The command-line parameter syntax is as follows:

 C:\>WMIProcess.wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIProcess.wsf /Action:value [/Executable[+|-]] [/CurrentDirectory:value]                       [/TerminateCode:value] [/PauseBeforeTerminate:value] [/ProcessID:value]                       [/Title:value] [/FillAttribute:value] [/PriorityClass:value]                       [/ShowWindow:value]                       [/X:value] [/XCountChars:value] [/XSize:value]                       [/Y:value] [/YCountChars:value] [/YSize:value]                       [/Machine:value] [/User:value] [/Password:value] Options: Action               : specify the operation to perform: [List] or [Create] or [Kill]. Executable           : The name of the executable to start. CurrentDirectory     : The directory where the process must be executed. (Default=C:\) TerminateCode        : Return code of the ended process. PauseBeforeTerminate : Pause before ending the started process (Default=10 s). ProcessID            : Process ID of the process to Kill. Title                : Contains the string displayed in the title bar if a new console window                        is created. FillAttribute        : Specifies the initial text and background colors if a new console window                        is created. PriorityClass        : Used to determine the scheduling priorities of the threads in the process.                        ShowWindow : Specifies how the window is to be displayed to the user. X                    : Specifies the x offset, in pixels, of the upper left corner of a window                        if a new window is created. XCountChars          : Used for processes creating a console window, specifies the screen buffer                        width in character columns. XSize                : Specifies the width, in pixels, of the window if a new window is created. Y                    : Specifies the y offset, in pixels, of the upper left corner of a window                        if a new window is created. YCountChars          : Used for processes creating a console window, specifies the screen buffer                        height in character rows. YSize                : Specifies the height, in pixels, of the window if a new window is created. 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:       WMIProcess.wsf /Action:List       WMIProcess.wsf /Action:List /Executable:NotePad.Exe       WMIProcess.wsf /Action:Create /Executable:NotePad.Exe /CurrentDirectory:C:\                      /PauseBeforeTerminate:4000 /TerminateCode:0       WMIProcess.wsf /Executable:NotePad.Exe /CurrentDirectory:C:\ /PauseBeforeTerminate:2000       WMIProcess.wsf /Executable:NotePad.Exe /CurrentDirectory:C:\ /TerminateCode:0       WMIProcess.wsf /Executable:CMD.Exe /FillAttribute:12 /PriorityClass:32 /ShowWindow:1                      /X:150 /XCountChars:40 /XSize:1024                      /Y:150 /YCountChars:10 /YSize:500       WMIProcess.wsf /Executable:CMD.Exe /Machine:RemoteSystem.LissWare.Net       WMIProcess.wsf /Action:Kill /ProcessID:1252 /TerminateCode:0       WMIProcess.wsf /Action:Kill /ProcessID:412 /TerminateCode:0                      /Machine:RemoteSystem.LissWare.Net 

To change the scripting technique used in the previous script samples, the next sample creates and kills processes asynchronously. From a global perspective, this does not change anything about the class usage, but the script structure and the scripting technique change significantly The code is presented in Sample 2.50 through 2.55. As usual, the script starts with the command-line parameters definition and parsing. Since the command-line parameters parsing code is structured in the same way as previously, it is omitted (lines 13 through 49 and 126 through 264) in the sample code visible below.

Sample 2.50: Viewing, creating, and killing processes (Part I)

start example

   l:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  49:    </runtime>  50:  51:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" />  52:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  53:  54:    <object progobjWMILocator' reference="true"/>  55:    <object prog  />  56:    <object prog  />  57:  58:    <script language="VBscript">  59:    <![CDATA[  ..:  63:    ' -----------------------------------------------------------------------------------------  64:    Const cComputerName = "LocalHost"  65:    Const cWMINameSpace = "root/cimv2"  66:    Const cWMIProcClass = "Win32_Process"  67:    Const cWMIProcStartupClass = "Win32_ProcessStartup"  68:  69:    Const cWMITerminateCode = 0  70:    Const cPauseBeforeTerminate = 10000  71:  72:    Const cFillAttribute = 12  73:    Const cPriorityClass = 32  74:    Const cShowWindow = 1  75:    Const cX = 100  76:    Const cXCountChars = 1000  77:    Const cXSize = 400  78:    Const cY = 100  79:    Const cYCountChars = 120  80:    Const cYSize = 300 ...: 124:    ' -------------------------------------------------------------------------------- 125:    ' Parse the command line parameters 126:    varTemp = WScript.Arguments.Named("TerminateCode") ...: ...: 264:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 265: 266:    Set objWMISink = WScript.CreateObject ("WbemScripting.SWbemSink", "SINK_") 267: 268:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 269:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 270: 271:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 272:                                                     strUserID, strPassword) ...: 274: ...: ...: ...: 

end example

The header of the script contains some constants (lines 69 through 80) that are used as default values when creating a new process. These constants are used later.

Sample 2.51 gathers information about the running processes. First, the script creates a collection of the process instances (line 284). Next, it enumerates the collection (lines 289 through 334) with all properties available from each instance (lines 292 through 312). Because many processes can run at the same time, the script uses the optional /Executable switch only to display information about the given executable name. However, because the executable name is not used as a key property of the Win32_Process class, the script queries for an instance using a name property that matches the executable name given (lines 278 through 281). As mentioned, the /Executable switch is optional; if no executable name is given (line 277), all instances will be listed.

Sample 2.51: Viewing processes (Part II)

start example

 ...: ...: ...: 274: 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 objWMIProcInstances 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 ...: 315:              WScript.Echo 316: 317:              intRC = objWMIProcInstance.GetOwner (strOwnerUser, strOwnerDomain) 318:              If intRC = 0 Then 319:                 DisplayFormattedProperty objWMIProcInstance, _ 320:                                          " Process owner", _ 321:                                          strOwnerDomain, _ 322:                                          strOwnerUser 323:              End If 324: 325:              intRC = objWMIProcInstance.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:          Next 335:       Else 336:          WScript.Echo "No information available." 337:       End If ...: 340: ...: ...: ...: 

end example

The Win32_Process class exposes two methods to retrieve information about the process owner. The GetOwner method (lines 317 through 323) retrieves the domain name and user name of the process owner, while the GetOwnerSID method (lines 325 through 331) retrieves the SID of the process owner. If you run the script to view process information about NotePad.Exe, you receive the following output:

  1:    C:\>WMIProcess.wsf /Action:List /Executable:Notepad.Exe  2:    Microsoft (R) Windows Script Host Version 5.6  3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.  4:  5:    - NOTEPAD.EXE------------------------------------------------------------  6:      CommandLine: ........................... "J:\WINDOWS\System32\Notepad.Exe" WMIProcessN.wsf  7:      CreationDate: .......................... 31-10-2001 16:32:22  8:      CSName: ................................ XP-DPEN6400  9:      ExecutablePath: ........................ J:\WINDOWS\System32\Notepad.Exe 10:      *Handle: ............................... 3532 11:      HandleCount: ........................... 22 12:      InstallDate: ........................... 31-10-2001 16:32:22 13:      KernelModeTime: ........................ 37754288 14:      MaximumWorkingSetSize: ................. 1413120 15:      MinimumWorkingSetSize: ................. 204800 16:      OSName: ................................ Microsoft Windows .NET Enterprise Server ... 17:      OtherOperationCount: ................... 44 18:      OtherTransferCount: .................... 432 19:      PageFaults: ............................ 776 20:      PageFileUsage: ......................... 692224 21:      ParentProcessId: ....................... 288 22:      PeakPageFileUsage: ..................... 692224 23:      PeakVirtualSize: ....................... 30711808 24:      PeakWorkingSetSize: .................... 3121152 25:      Priority: .............................. 8 26:      PrivatePageCount: ...................... 692224 27:      ProcessId: ............................. 3532 28:      QuotaNonPagedPoolUsage: ................ 1680 29:      QuotaPagedPoolUsage: ................... 26672 30:      QuotaPeakNonPagedPoolUsage: ............ 1760 31:      QuotaPeakPagedPoolUsage: ............... 33136 32:      ReadOperationCount: .................... 0 33:      ReadTransferCount: ..................... 0 34:      SessionId: ............................. 0 35:      TerminationDate: ....................... 31-10-2001 16:32:22 36:      ThreadCount: ........................... 1 37:      UserModeTime: .......................... 3404896 38:      VirtualSize: ........................... 24297472 39:      WindowsVersion: ........................ 5.1.3553 40:      WorkingSetSize: ........................ 3121152 41:      WriteOperationCount: ................... 0 42:      WriteTransferCount: .................... 0 43: 44:      Process owner: ......................... LISSWARENET Alain.Lissoir 45:      Process owner SID: ..................... S-1-5-21-2025429265-507921405-1202660629-1140 

Note that none of the listed properties displays information about the process CPU usage. This information is available from the performance counters. We discuss how to retrieve this in the next chapter.

To create a process, the Create method of the Win32_Process class is used (see Sample 2.52). It is important to note that the Create method is a static method for the class. This implies that a static qualifier is set on the Create method definition, which means that the method invocation must be made from an instance of the Win32_Process class (line 343). We have already seen this peculiarity when we worked with Sample 2.12 ("Configuring a network adapter"). Next, when creating a new process, it is possible to specify a series of parameters for the created process. These parameters are stored in a class instance of the Win32_ProcessStartup class (lines 346 through 349). The Win32_ProcessStartup class is a bit unusual, because it is defined as an abstract class. (See Figure 2.18.)

Sample 2.52: Creating processes (Part II)

start example

 ...: ...: ...: 340: 341:    ' - CREATE -------------------------------------------------------------------------------- 342:    ElseIf boolCreate Then 343:       Set objWMIProcClass = objWMIServices.Get (cWMIProcClass) ...: 346:       Set objWMIProcStartupClass = objWMIServices.Get (cWMIProcStartupClass) ...: 349:       Set objWMIProcStartupInstance = objWMIProcStartupClass.SpawnInstance_ 350: 351:       objWMIProcStartupInstance.FillAttribute = intFillAttribute 352:       objWMIProcStartupInstance.PriorityClass = intPriorityClass 353:       objWMIProcStartupInstance.ShowWindow = intShowWindow 354:       objWMIProcStartupInstance.Title = strTitle 355:       objWMIProcStartupInstance.X = intX 356:       objWMIProcStartupInstance.XCountChars = intXCountChars 357:       objWMIProcStartupInstance.XSize = intXSize 358:       objWMIProcStartupInstance.Y = intY 359:       objWMIProcStartupInstance.YCountChars = intYCountChars 360:       objWMIProcStartupInstance.YSize = intYSize 361: 362:       objWMIMethodSinkContext.Add "WMIMethod", "Create" 363:       Set objWMIMethod = objWMIProcClass.Methods_("Create") 364:       Set objWMIInParameters = objWMIMethod.InParameters 365: 366:       objWMIInParameters.Properties_.Item("CommandLine") = strExecutable 367:       objWMIInParameters.Properties_.Item("CurrentDirectory") = strCurrentDirectory 368:       objWMIInParameters.Properties_.Item("ProcessStartupInformation") = _ 369:                                                  objWMIProcStartupInstance 370: 371:       objWMIProcClass.ExecMethodAsync_ objWMISink, _ 372:                                        "Create", _ 373:                                        objWMIInParameters, _ 374:                                        wbemFlagDontSendStatus, _ 375:                                        ,_ 376:                                        objWMIMethodSinkContext ...: 384:       Do While (boolEndScript = False) 385:          WScript.Sleep (500) 386:       Loop 387: 388:       objWMISink.Cancel 389: ...: ...: ...: 

end example


Figure 2.18: The Win32_ProcessStartup abstract class used only as a method parameter class.

The Win32_ProcessStartup is a child class of the Win32_MethodParameterClass class. The classes defined as a subclass of the Win32_MethodParameterClass class are only used to create an instance used as a method parameter. The Win32_ProcessStartup properties set by the script are only applicable if the created process is a console application (lines 351 through 360).

Next, since the script is executed asynchronously, the sink routine context is defined (line 362) and the Create method parameters are set (lines 363 through 369). Line 366 sets the executable to be started, line 367 defines the default directory for the new process, and line 368 stores the Win32_ProcessStartup instance that contains the optional parameters for a console application. Once completed, the method execution is invoked asynchronously (lines 371 through 376). Next, the script waits for the end of the asynchronous operation (lines 384 through 386).

Before diving into the sink subroutines, since the kill process operation is also asynchronously executed with the same set of sink routines, let's see how the Terminate method of the Win32_Process class is invoked with Sample 2.53. This method is not a static method and relates to an instance of an existing process. This is the reason why the script first retrieves the process instance by using its process ID, which is used as a key property for the Win32_Process class (line 392). The process ID is retrieved during the asynchronous execution of the process creation (line 438 and following). Next, a context is defined for the asynchronous method invocation. This context is used later during the sink routine's execution.

Sample 2.53: Killing processes (Part IV)

start example

 ...: ...: ...: 389: 390:    ' - KILL --------------------------------------------------------------------------------- 391:    ElseIf boolKill Then 392:       Set objWMIProcInstance = objWMIServices.Get (cWMIProcClass & "='" & intProcID & "'") 393:       If Err.Number Then ErrorHandler (Err) 394: 395:       objWMIMethodSinkContext.Add "WMIMethod", "Terminate" 396:       Set objWMIMethod = objWMIProcInstance.Methods_("Terminate") 397:       Set objWMIInParameters = objWMIMethod.InParameters 398: 399:       objWMIInParameters.Properties_.Item("Reason") = intTerminateCode 400:       objWMIProcInstance.ExecMethodAsync_ objWMISink, _ 401:                                           "Terminate", _ 402:                                           objWMIInParameters, _ 403:                                           wbemFlagDontSendStatus, _ 404:                                           , _ 405:                                           objWMIMethodSinkContext ...: 410:       Do While (boolEndScript = False) 411:          WScript.Sleep (500) 412:       Loop 413: 414:       objWMISink.Cancel 415:    End If ...: 421: ...: ...: ...: 

end example

Because it is possible to specify a termination code, the script makes use of the /TerminateCode switch and assigns the given value at line 399. Next, the method is asynchronously invoked (lines 400 through 405). As previously, the script waits for the end of the asynchronous operation (lines 410 through 412).

The asynchronous sink routines are shown in Sample 2.54. Two event sinks are used: the SINK_OnCompleted() (lines 423 through 457) and SINK_OnObjectReady() (lines 460 through 531).

Sample 2.54: Viewing, creating, and killing processes (OnObjectReady sink routine) (Part V)

start example

 ...: ...: ...: 421: 422:    ' ---------------------------------------------------------------------------------------- 423:    Sub SINK_OnObjectReady (objWMIInstance, objWMIAsyncContext) ...: 429:        Wscript.Echo 430:        Wscript.Echo "BEGIN - OnObjectReady." 431: 432:        Set objContextItem = objWMIAsyncContext.Item ("WMIMethod") ...: 435:        Select Case objContextItem.Value 436:               Case "Create" 437:                    If objWMIInstance.ReturnValue = 0 Then 438:                       intProcID = objWMIInstance.ProcessID 439:                       WScript.Echo "Process ID " & intProcID & " created." 440:                    Else 441:                       Wscript.Echo "Asynchronous method execution failed (" & _ 442:                                    objWMIInstance.ReturnValue & ")." 443:                    End If 444:               Case "Terminate" 445:                    If objWMIInstance.ReturnValue = 0 Then 446:                       WScript.Echo "Process ID " & intProcID & " terminated." 447:                    Else 448:                       Wscript.Echo "Asynchronous method execution failed (" & _ 449:                                    objWMIInstance.ReturnValue & ")." 450:                    End If 451:        End Select ...: 455:        Wscript.Echo "END - OnObjectReady." 456: 457:    End Sub 458: ...: ...: ...: 

end example

When a Win32_Process method is executed asynchronously (i.e., for the Create or Terminate methods), the code first determines its context (lines 432 and 435). If a process is created (lines 436 through 443), the Process ID of the newly created process is saved in a variable at line 438. This variable is used later to retrieve the instance of the process to kill, as well as during the SINK_OnCompleted() sink routine once the process is successfully killed. In the context Terminate method execution, the return value of the Terminate method is tested, and a message is displayed accordingly (lines 444 through 450).

Once the asynchronous operation is completed, the SINK_OnCompleted() sink routine is called. This routine contains some extra logic based on the command-line parameters given.

Sample 2.55: Viewing, creating, and killingprocesses (On Completed sink routine) (Part VI)

start example

 ...: ...: ...: 458: 459:    ' --------------------------------------------------------------------------------------- 460:    Sub SINK_OnCompleted (intHResult, objWMILastError, objWMIAsyncContext) ...: 467:        Wscript.Echo 468:        Wscript.Echo "BEGIN - OnCompleted." 469: 470:        Set objContextItem = objWMIAsyncContext.Item ("WMIMethod") ...: 473:        If intHResult = 0 Then 474:           WScript.Echo "'" & objContextItem.Value & _ 475:                        "' WMI Scripting API Asynchronous call successful " & _ 476:                        "(" & intHResult & ")." 477: 478:           Select Case objContextItem.Value 479:                  Case "Create" 480:                       If intTerminateCode <> -1 And intProcID <> 0 Then 481:                          WScript.Echo "Pausing script execution for " & _ 482:                                       intPauseBeforeTerminate / 1000 & _ 483:                                       " seconds before ending procees ID " & _ 484:                                       intProcID & " ..." 485:                          WScript.Sleep (intPauseBeforeTerminate) 486: 487:                          Set objWMIProcInstance = objWMIServices.Get (cWMIProcClass & "='" & _ 488:                                                                      intProcID & "'") ...: 491:                          objWMIMethodSinkContext.Add "WMIMethod", "Terminate" 492:                          Set objWMIMethod = objWMIProcInstance.Methods_("Terminate") 493:                          Set objWMIInParameters = objWMIMethod.InParameters 494: 495:                          objWMIInParameters.Properties_.Item("Reason") = intTerminateCode 496:                          objWMIProcInstance.ExecMethodAsync_ objWMISink, _ 497:                                                              "Terminate", _ 498:                                                              objWMIInParameters, _ 499:                                                              wbemFlagDontSendStatus, _ 500:                                                              , _ 501:                                                              objWMIMethodSinkContext ...: 505:                       Else 506:                          boolEndScript = True 507:                       End If 508:                  Case "Terminate" 509:                       boolEndScript = True 510:           End Select 511:        Else 512:           WScript.Echo String (60, "-") 513: 514:           WScript.Echo "'" & objContextItem.Value & _ 515:                        "' WMI Scripting API Asynchronous call failed " & _ 516:                        "(" & intHResult & ")." 517: 518:           WScript.Echo vbCRLF & "SWbemLastError content:" 519:           Set objWMIPropertySet = objWMILastError.Properties_ 520:           For Each objWMIProperty In objWMIPropertySet 521:               WScript.Echo "  " & objWMIProperty.Name & "=" & objWMIProperty.Value 522:           Next 523:           Set objWMIPropertySet = Nothing 524:           WScript.Echo String (60, "-") 525:        End If ...: 529:        Wscript.Echo "END - OnCompleted." 530: 531:    End Sub 532: 533:    ]]> 534:    </script> 535:  </job> 536:</package> 

end example

At line 470, the script first determines the context of the WMI asynchronous operation (Create or Terminate method execution). Based on its result (line 473), the script displays an informational message (lines 474 and 475 or 512 through 524). If the asynchronous context operation corresponds to a process creation (lines 480 through 507), the code performs some extra tests. These tests are done with the variables that contain information given on the command line. Let's take an example. To create a process, the following command line can be given:

 WMIProcess.wsf /Action:Create /Executable:NotePad.Exe /CurrentDirectory:C:\ 

This command line creates a process called NotePad.Exe with a default directory of C:\. Once the process is created, the script terminates properly. The obtained output is as follows:

 C:\>WMIProcess.wsf /Action:Create /Executable:NotePad.Exe /CurrentDirectory:C:\ Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. BEGIN - OnObjectReady. Process ID 4092 created. END - OnObjectReady. BEGIN - OnCompleted. 'Create' WMI Scripting API Asynchronous call successful (0). END - OnCompleted. 

However, with the logic implemented in the SINK_OnCompleted() sink routine it is also possible to start a process for a defined period of time, and, once this time elapses, the created process is automatically killed by the script itself. The command line to use, and the output obtained, is as follows:

 C:\>WMIProcess.wsf /Action:Create /Executable:NotePad.Exe /CurrentDirectory:C:\                                   /PauseBeforeTerminate:4000 /TerminateCode:0 Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. BEGIN - OnObjectReady. Process ID 3596 created. END - OnObjectReady. BEGIN - OnCompleted. 'Create' WMI Scripting API Asynchronous call successful (0). Pausing script execution for 4 seconds before ending procees ID 3596 ... END - OnCompleted. BEGIN - OnObjectReady. Process ID 3596 terminated. END - OnObjectReady. BEGIN - OnCompleted. 'Terminate' WMI Scripting API Asynchronous call successful (0). END - OnCompleted. 

The fact that the /TerminateCode is given on the command line with the /Action:Create switch forces the script to kill the newly created process before ending. The /PauseBeforeTerminate switch forces a pause of four seconds. If the /PauseBeforeTerminate switch is not given, a default pause of ten seconds is made. This default timeout is defined in the constant defined in the script header (see Sample 2.50, line 70).

From a coding point of view, the value given with the /TerminateCode switch is tested to determine if the new process must be killed. This test is made at line 480. On the same line the Process ID value saved during the SINK_OnObjectReady() sink routine (see Sample 2.54) is reused. If the test evaluation is successful (line 480), it means that a pause must be performed (line 485). Once the pause ends, the script retrieves an instance of the created process (lines 487 and 488). Next, we retrieve the same logic as before to kill a process asynchronously (lines 491 through 501).

If the /Terminate switch is not given, the script sets a Boolean variable to True (line 506) to terminate the loop waiting for the end of the asynchronous operation (see Sample 2.52, lines 384 through 386). If the /Terminate switch is given, and once the newly created process is killed, the SINK_OnCompleted() sink routine is called a second time for the Terminate method asynchronous execution. In the same way, the script sets the Boolean variable to True (line 509) to terminate the loop waiting for the end of the asynchronous operation (see Sample 2.52, lines 384 through 386).

When the script is used to kill a process based on its process ID, the following command line is used:

 WMIProcess.wsf /Action:Kill /ProcessID:412 /TerminateCode:0 

In this case, the dedicated piece of code executed is located between lines 444 and 450 in the SINK_OnObjectReady() sink routine and line 509 in the SINK_OnCompleted() sink routine. At line 509, you will notice the Boolean variable value set on True to stop the loop waiting for the end of the asynchronous operation (see Sample 2.53, lines 410 through 412).

2.4.10 Registry class

The class in the registry category represents the settings of the Windows registry. There is only one class, called Win32_Registry. It is important to avoid confusion between this class and the classes exposed by the WMI Registry provider. The Win32_Registry class represents the Windows registry settings, such as the registry size, while the WMI Registry provider exposes classes and methods that allow access and event monitoring of the Windows registry data. We examine the WMI Registry provider, its related classes, and how to manipulate the registry content in the next chapter.

When we learned the WMI scripting technique in Understanding WMI Scripting, Chapter 4, we used the Win32_Registry class. Instead of reproducing one of these samples, you can refer to the appendix for Sample 4.14 ("Setting one read/write property of a Win32_Registry class instance directly") and Sample 4.15 ("Setting one read/write property of a Win32_ Registry class instance indirectly"). The Win32_Registry class exposes only one read/write property, called ProposedSize. All other properties are readonly, and there is no method available from the class.

2.4.11 Job scheduler classes

The job scheduler classes category represents scheduled job settings. This category contains only two classes, listed in Table 2.25.

Table 2.25: The Job Scheduler Classes

Name

Type

Description

Win32_CurrentTime

Abstract

Represents as Dynamic in time as component seconds, minutes, day of the week, and so on.

Win32_ScheduledJob

Dynamic

Represents a job scheduled using the Windows NT schedule service.

The Win32_ScheduledJob class with its two methods implements the necessary features to develop a script equivalent to the AT.Exe command. With this class, it is possible to view, create, and delete scheduled jobs. Even if the Win32_CurrentTime class is categorized in the Jobs Scheduler category in the Microsoft Platform SDK, it is important to note that this class is supported by the Win32Clockprovider WMI provider and not by the Win32 providers. We examine this provider and its related Win32_CurrentTime class in the next chapter.

As in previous scripts, the next sample supports a set of command-line parameters. Each of the switches corresponds to one of the features supported by the classes. The command-line parameters supported are:

 C:\>WMIScheduledJob.wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIScheduledJob.wsf [/List[+|-]] [/Create:value] [/StartTime:value] [/RunRepeatedly[+|-]]                            [/DaysOfWeek:value] [/DaysOfMonth:value] [/InteractWithDesktop[+|-]]                            [/Delete:value] [/GetTime[+|-]] [/Machine:value] [/User:value]                            [/Password:value] Options: List                : List the existing scheduled jobs. Create              : The name of the executable to start. StartTime           : Represents the UTC time to run the job. RunRepeatedly       : Indicates whether the scheduled job should run repeatedly on the days that                       the job is scheduled. DaysOfWeek          : Indicates the days of the week when the job is scheduled to run                       (used with RunRepeatedly). DaysOfMonth         : Indicates the days of the month when the job is scheduled to run                       (used with RunRepeatedly). InteractWithDesktop : Indicates whether the specified job should be interactive. Delete              : Deletes a scheduled job. GetTime             : Get the current time in UTC format. 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:       WMIScheduledJob.wsf /GetTime+       WMIScheduledJob.wsf /List+       WMIScheduledJob.wsf /Create:MyJob.Exe /StartTime:********180000.000000+120                           /DaysOfWeek:Mon,Tue,Wed,Thu,Fri,Sat,Sun                           /DaysOfMonth:1,2,3,4,24       WMIScheduledJob.wsf /Delete:9,15,17,18,23       WMIScheduledJob.wsf /Delete:14 

The complete script code is shown in Samples 2.56 through 2.59. As with all previous scripts, Sample 2.56 starts with the command-line parameters definition (skipped lines 13 through 37) and parsing (lines 96 through 183). Although very similar to the command-line parsing technique used in the previous scripts, we will briefly examine this piece of code, because it requires some special care to build two required parameters of the Create method exposed by the Win32_ScheduledJob class. These two parameters are DaysOfWeek and DaysOfMonth.

Sample 2.56: Viewing, creating, and deleting scheduled jobs (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\DecodeDaysOfWeekFunction.vbs" />  40:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodeDaysOfMonthFunction.vbs" />  41:  42:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\ConvertStringInArrayFunction.vbs" />  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="VBscript">  50:    <![CDATA[  ..:  54:    ' ----------------------------------------------------------------------------------------  55:    Const cComputerName = "LocalHost"  56:    Const cWMINameSpace = "root/cimv2"  57:  58:    Const cWMIScheduledJobClass = "Win32_ScheduledJob"  ..:  94:    ' --------------------------------------------------------------------------------  95:    ' Parse the command line parameters  96:    If WScript.Arguments.Named.Count = 0 Then  97:       WScript.Arguments.ShowUsage()  98:       WScript.Quit  99:    End If 100: 101:    boolList = WScript.Arguments.Named("List") 102:    If Len(boolList) = 0 Then boolList = False 103: 104:    boolGetTime = WScript.Arguments.Named("GetTime") 105:    If Len(boolGetTime) = 0 Then boolGetTime = False 106: 107:    varTemp = WScript.Arguments.Named("Delete") 108:    If Len (varTemp) Then 109:       arrayJobIDToDelete = ConvertStringInArray (varTemp, ",") 110:       boolJobIDToDelete = True 111:    Else 112:       boolJobIDToDelete = False 113:    End If 114: 115:    strJobToCreate = WScript.Arguments.Named("Create") 116:    If Len (strJobToCreate) = 0 And _ 117:       boolList = False And _ 118:       boolGetTime = False And _ 119:       boolJobIDToDelete = False Then 120:       WScript.Arguments.ShowUsage() 121:       WScript.Quit 122:    End If 123: 124:    strStartTime = WScript.Arguments.Named("StartTime") 125:    If Len (strStartTime) = 0 And _ 126:       boolList = False And _ 127:       boolGetTime = False And _ 128:       boolJobIDToDelete = False Then 129:       WScript.Arguments.ShowUsage() 130:       WScript.Quit 131:    End If 132: 133:    boolRunRepeatedly = WScript.Arguments.Named("RunRepeatedly") 134:    If Len(boolRunRepeatedly) = 0 Then boolRunRepeatedly = False 135: 136:    varTemp = WScript.Arguments.Named("DaysOfWeek") 137:    If Len (varTemp) Then 138:       arrayDaysOfWeek = ConvertStringInArray (varTemp, ",") 139:       For Each strDayOfWeek In arrayDaysOfWeek 140:           Select Case Ucase (strDayOfWeek) 141:                  Case "MON" 142:                       intIndice = 0 143:                  Case "TUE" 144:                       intIndice = 1 145:                  Case "WED" 146:                       intIndice = 2 147:                  Case "THU" 148:                       intIndice = 3 149:                  Case "FRI" 150:                       intIndice = 4 151:                  Case "SAT" 152:                       intIndice = 5 153:                  Case "SUN" 154:                       intIndice = 6 155:                  Case Else 156:                       WScript.Echo "Invalid day of week. Only Mon, Tue, ..." & vbCRLF 157:                       WScript.Arguments.ShowUsage() 158:                       WScript.Quit 159:           End Select 160:           intDaysOfWeek = intDaysOfWeek + 2^intIndice 161:       Next 162:    Else 163:       intDaysOfWeek = 0 164:    End If 165: 166:    varTemp = WScript.Arguments.Named("DaysOfMonth") 167:    If Len (varTemp) Then 168:       arrayDaysOfMonth = ConvertStringInArray (varTemp, ",") 169:       For Each intIndice In arrayDaysOfMonth 170:           If intIndice < 1 Or intIndice > 31 Then 171:              WScript.Echo "Invalid day of month. Only numbers from to 1 to 31 ..." & vbCRLF 172:              WScript.Arguments.ShowUsage() 173:              WScript.Quit 174:           Else 175:              intDaysOfMonth = intDaysOfMonth + 2^(intIndice - 1) 176:           End If 177:       Next 178:    Else 179:       intDaysOfMonth = 0 180:    End If 181: 182:    boolInteractWithDesktop = WScript.Arguments.Named("InteractWithDesktop") 183:    If Len(boolInteractWithDesktop) = 0 Then boolInteractWithDesktop = False ...: 194:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 195:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 196: 197:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 198:                                                     strUserID, strPassword) ...: 200: ...: ...: ...: 

end example

Most of the command-line parameters are easily parsed and checked in a few lines, as shown previously. However, regarding the DaysOfWeek and DaysOfMonth parameters, the string given on the command line must be converted to a specific value, which represents the days of the week (lines 136 through 164) or the days of the month (lines 166 through 180). For the days of the week, each bit of the value represents a specific day of the week (from bit 0 to 6):

  • Bit 0—Monday, which defines a value of 1 to activate the job on Monday.

  • Bit 1—Tuesday, which defines a value of 2 to activate the job on Tuesday.

  • Bit 2—Wednesday, which defines a value of 4 to activate the job on Wednesday.

  • Bit 3—Thursday, which defines a value of 8 to activate the job on Thursday.

  • Bit 4—Friday, which defines a value of 16 to activate the job on Friday.

  • Bit 5—Saturday, which defines a value of 32 to activate the job on Saturday.

  • Bit 6—Sunday, which defines a value of 64 to activate the job on Sunday.

So, to activate a job on Monday, Wednesday, and Friday, the command line to use is:

 C:\>WMIScheduledJob.wsf /Create:MyJob.Exe /StartTime:********180000.000000+120                         /DaysOfWeek:Mon,Wed,Fri 

The resulting value is 1 + 4 + 16 = 21. When the /DaysOfWeek switch is read, the abbreviation of the days given in a comma-delimited string is converted in an array with the help of the ConvertStringInArray() function, included at line 42. Next, this array is enumerated, and, for each day found, a corresponding bit value is used to calculate the value of the day (lines 139 through 161).

For the days of the month, the principle is exactly the same as for the days of the week. The command line to use is:

 WMIScheduledJob.wsf /Create:MyJob.Exe /StartTime:********180000.000000+120                    /DaysOfMonth:3,5,10,25,30 

Each bit corresponds to a day of the month, and the value uses 31 bits to cover a complete month (from bit 0 to 30).

  • Bit 0—1st day of the month, which defines a value of 1 to activate the job the 1st day.

  • Bit 1—2nd day of the month, which defines a value of 2 to activate the job the 2nd day.

  • Bit 2—3rd day of the month, which defines a value of 4 to activate the job the 3rd day.

    ...

  • Bit 29—30th day of the month, which defines a value of 536 870 912 to activate the job the 30th day.

  • Bit 30—31st day of the month, which defines a value of 1 073 741 824 to activate the job the 31st day.

So, to activate a job on the 3rd, 5th, 10th, 25th, and 30th days of the month, the resulting value must be 4 + 16 + 512 + 16 777 216 + 536 870 912 = 553 648 660.

Based on the day numbers given with the /DaysOfMonth switch, lines 168 through 177 are used to calculate the value. These two calculated values are used when a scheduled job is created.

When the /List+ switch is given on the command line, the portion of code available in Sample 2.57 is executed. This code does not contain anything unusual. It creates a collection of instances from the Win32_ScheduledJob class (line 203). This collection represents the list of scheduled jobs available in the computer. Next, this collection is enumerated with each property of the Win32_ScheduledJob class (lines 207 through 232). Note the conversion of the DaysOfTheWeek (line 221) and DaysOfTheMonth (line 216) properties.

Sample 2.57: Viewing the scheduled jobs (Part II)

start example

 ...: ...: ...: 200: 201:    ' LIST ----------------------------------------------------------------------------------- 202:    If boolList Then 203:       Set objWMIInstances = objWMIServices.InstancesOf (cWMIScheduledJobClass) ...: 206:       If objWMIInstances.Count Then 207:          For Each objWMIInstance in objWMIInstances 208:              WScript.Echo "- Scheduled jobs (" & objWMIInstance.JobID & _ 209:                           ") " & String (60, "-") 210:              Set objWMIPropertySet = objWMIInstance.Properties_ 211:              For Each objWMIProperty In objWMIPropertySet 212:                  Select Case objWMIProperty.Name 213:                         Case "DaysOfMonth" 214:                              DisplayFormattedProperty objWMIInstance, _ 215:                                                       objWMIProperty.Name, _ 216:                                                       DaysOfMonth (objWMIProperty.Value), _ 217:                                                       Null 218:                         Case "DaysOfWeek" 219:                              DisplayFormattedProperty objWMIInstance, _ 220:                                                       objWMIProperty.Name, _ 221:                                                       DaysOfWeek (objWMIProperty.Value), _ 222:                                                       Null 223:                         Case Else 224:                              DisplayFormattedProperty objWMIInstance, _ 225:                                                       objWMIProperty.Name, _ 226:                                                       objWMIProperty.Name, _ 227:                                                       Null 228:                  End Select 229:              Next 230:              Set objWMIPropertySet = Nothing 231:              WScript.Echo 232:          Next 233:       Else 234:          WScript.Echo "No scheduled job." 235:       End If 236:    End If 237: ...: ...: ...: 

end example

The creation of a new scheduled job can be made with the following command lines:

 C:\>WMIScheduledJob.wsf /Create:MyJob.Exe /StartTime:********180000.000000+120 

or:

 C:\>WMIScheduledJob.wsf /Create:MyJob.Exe /StartTime:********180000.000000+120                      /DaysOfWeek:Mon,Tue,Wed,Thu,Fri,Sat,Sun 

or:

 C:\>WMIScheduledJob.wsf /Create:MyJob.Exe /StartTime:********180000.000000+120                      /DaysOfMonth:1,2,3,4,24 

or:

 C:\>WMIScheduledJob.wsf /Create:MyJob.Exe /StartTime:********180000.000000+120                     /DaysOfWeek:Mon,Tue,Wed,Thu,Fri,Sat,Sun /DaysOfMonth :1,2,3,4,24 

Once the command-line parameters are parsed (as explained previously), the scheduled job is created with the use of the Create method exposed by the Win32_ScheduledJob class. This portion of the code is shown in Sample 2.58. Again, as seen in some of the previous samples, the method is defined in the CIM repository as a static method. Doing so, the script must invoke the method from a Win32_ScheduledJob class instance (lines 240 through 243).

Sample 2.58: Creating scheduled jobs (Part III)

start example

 ...: ...: ...: 237: 238:    ' CREATE ---------------------------------------------------------------------------------- 239:    If Len (strJobToCreate) Then 240:       Set objWMIClass = objWMIServices.Get (cWMIScheduledJobClass) 241:       If Err.Number Then ErrorHandler (Err) 242: 243:       intRC = objWMIClass.Create (strJobToCreate, _ 244:                                   strStartTime, _ 245:                                   boolRunRepeatedly, _ 246:                                   intDaysOfWeek, _ 247:                                   intDaysOfMonth, _ 248:                                   boolInteractWithDesktop, _ 249:                                   intJobID) 250:       If Err.Number Then ErrorHandler (Err) 251: 252:       WScript.Echo "Schedule job " & intJobID & " created (" & intRC & ")." 253 : 254:       Set objWMIInstance = Nothing 255: 256:    End If 257: ...: ...: ...: 

end example

A scheduled job is simply deleted by invoking the Delete_ method of the SWBemObject representing the instance of the scheduled job (see Sample 2.59). For this, an instance of the job must first be retrieved (lines 261 and 262). Next, the retrieved instance is deleted (line 265). Note that the deletion is made in a loop, because the /Delete switch accepts several job IDs.

Sample 2.59: Deleting scheduled jobs (Part IV)

start example

 ...: ...: ...: 257: 258:    ' DELETE --------------------------------------------------------------------------------- 259:    If boolJobIDToDelete Then 260:       For intIndice = 0 To Ubound (arrayJobIDToDelete) 261:           Set objWMIInstance = objWMIServices.Get (cWMIScheduledJobClass & "=" & _ 262:                                                    arrayJobIDToDelete(intIndice)) 263:           If Err.Number Then ErrorHandler (Err) 264: 265:           objWMIInstance.Delete_ 266:           If Err.Number Then ErrorHandler (Err) 267: 268:           WScript.Echo "Scheduled Job " & arrayJobIDToDelete(intIndice) & " deleted." 269: 270:           Set objWMIInstance = Nothing 271:       Next 272:    End If 273: ...: ...: ...: 

end example

This allows the deletion of several scheduled jobs in one script execution. For instance, the command-line parameter for such an operation is as follows:

 C:\>WMIScheduledJob.wsf /Delete:9,15,17,18,23 

2.4.12 Service classes

The service classes category represents the Windows services and base services. There are only two classes in this category: Win32_BaseService and Win32_Service (see Table 2.26).

Table 2.26: The Service Classes

Name

Description

Win32_BaseService

Represents executable objects that are installed in a registry database maintained by the Service Control Manager.

Win32 Service

Represents a service on a Windows computer system.

The Win32_BaseService is a superclass for the Win32_Service class. We examined these classes in a different context throughout the first book, Understanding WMI Scripting, and are familiar with them. However, the Create, Change, and Delete methods exposed by the Win32_Service method were not used previously. Samples 2.60 through 2.64 illustrate the use of these methods, and the command-line parameters from the script are as follows:

 C:\>WMIServices.Wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIServices.wsf /Action:value /Name:value /DisplayName:value /PathName:value                        /ServiceType:value /ErrorControl:value /StartMode:value                        [/DesktopInteract[+|-]] [/StartName:value] [/StartPassword:value]                        [/LoadOrderGroup:value] [/LoadOrderGroupDependencies:value]                        [/ServiceDependencies:value] [/Machine:value] [/User:value]                        [/Password:value] Options: Action                     : Specify the operation to perform. Only [list], [create], [update] or                              [delete] are accepted. Name                       : Name of the service to install. DisplayName                : Display name of the service. PathName                   : Fully-qualified path to the executable file that implements                              the service. ServiceType                : 1=Kernel Driver, 2=File System Driver, 4=Adapter, 8=Recognizer Driver,                              16=Own Process, 32=Share Process, 256=Interactive Process ErrorControl               : 0=User is not notified, 1=User is notified, 2=System is restarted with                              last-known-good configuration, 3=System attempts to start with a good                              configuration. StartMode                  : Start mode of the service. Only [Boot], [System], [Automatic], [Manual]                              or [Disabled] are accepted. DesktopInteract            : If TRUE, the service can create or communicate with windows on the                              desktop. StartName                  : Account name under which the service runs. If empty, the LocalSystem                              account is used. StartPassword              : Password to the account name specified by the StartName parameter. LoadOrderGroup             : Group name associated with the new service. LoadOrderGroupDependencies : List of load-ordering groups that must start before this service. ServiceDependencies        : List containing names of services that must start before this service                              starts. 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) Example:       WMIServices.Wsf /Action:Create /Name:"MySNMP" /DisplayName:"My SNMP Service"                       /PathName:"J:\WINDOWS\System32\snmp.exe" /ServiceType:16                       /ErrorControl:1 /StartMode:"Manual"       WMIServices.Wsf /Action:Update /Name:"MySNMP" /DisplayName:"My SNMP Service"                       /PathName:"J:\WINDOWS\System32\snmp.exe" /ServiceType:16 /ErrorControl:1                       /StartMode:"Automatic" WMIServices.Wsf /Action:Delete /Name:"MySNMP" 

The creation of a service requires many parameters. However, the command-line parsing continues to use the same logic and scripting techniques (omitted lines 13 through 40 and lines 92 through 179). (See Sample 2.60.)

Sample 2.60: Creating, updating, and deleting a Win32_Service (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\ConvertStringInArrayFunction.vbs" />  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="VBscript">  50:    <![CDATA[  ..:  54:    Const cComputerName = "LocalHost"  55:    Const cWMINameSpace = "root/cimv2"  56:    Const cWMIClass = "Win32_Service"  ..:  90:    ' --------------------------------------------------------------------------------  91:    ' Parse the command line parameters  92:    If WScript.Arguments.Named.Count Then  93:       Select Case Ucase(WScript.Arguments.Named("Action"))  94:              Case "LIST"  95:                   boolList = True  96:              Case "CREATE"  97:                   boolCreate = True  98:              Case "UPDATE"  99:                   boolUpdate = True 100:              Case "DELETE" 101:                   boolDelete = True 102:              Case Else 103:                   WScript.Echo "Invalid action type. Only [List], [Create], ..." & vbCRLF 104:                   WScript.Arguments.ShowUsage() 105:                   WScript.Quit 106:       End Select ...: 178:    strComputerName = WScript.Arguments.Named("Machine") 179:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 180: 181:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 182:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 183: 184:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 185:                                                     strUserID, strPassword) 186:    If Err.Number Then ErrorHandler (Err) 187: ...: ...: ...: 

end example

The code of Sample 2.61 lists the Windows services available in a system. This routine is included in the script for functionality completeness. There is no need to make any particular comments on the code presented in Sample 2.61, since the scripting technique is very well known.

Sample 2.61: Viewing the Win32_Service instances (Part II)

start example

 ...: ...: ...: 187: 188:    ' -- LIST --------------------------------------------------------------------------- 189:    If boolList = True Then 190:       Set objWMIInstances = objWMIServices.InstancesOf (cWMIClass) 191: 192:       For Each objWMIInstance In objWMIInstances 193:           WScript.Echo "- " & objWMIInstance.DisplayName & _ 194:                        " (" & objWMIInstance.Name & ") " & _ 195:                        String (60, "-") 196:           Set objWMIPropertySet = objWMIInstance.Properties_ 197:           For Each objWMIProperty In objWMIPropertySet 198:               Select Case objWMIProperty.Name 199:                      Case "" 200: 201:                      Case Else 202:                           DisplayFormattedProperty objWMIInstance, _ 203:                                                    objWMIProperty.Name, _ 204:                                                    objWMIProperty.Name, _ 205:                                                    Null 206:               End Select 207:           Next 208:           Set objWMIPropertySet = Nothing 209:           WScript.Echo 210:       Next 211: 212:       WScript.Echo vbCRLF & "Completed." ...: 215:    End If 216: ...: ...: ...: 

end example

To create, modify, and delete a Windows service, the script uses the three methods defined at the level of the Win32_BaseService class. The Create method requires 12 parameters. Although most of the parameters to use with the script sample are obvious, the ServiceType, ErrorControl, and StartMode parameters are summarized in Table 2.27.

Table 2.27: The ServiceType, ErrorControl, and StartMode Parameters for a Windows Service Creation

ServiceType

Value

Description

1

Kernel Driver

2

File System Driver

4

Adapter

8

Recognizer Driver

16

Own Process

32

Share Process

256

Interactive Process

ErrorControl

Value

Description

0

User is not notified.

1

User is notified.

2

System is restarted with last-known-good configuration.

3

System attempts to start with a good configuration.

StartMode

Value

Description

Boot

Device driver started by the operating system loader. This value is valid only for driver services.

System

Device driver started by the IoInitSystem method. This value is valid only for driver services.

Automatic

Service to be started automatically by the service control manager during system startup.

Manual

Service to be started by the service control manager when a process calls the StartService method.

Disabled

Service that can no longer be started.

As shown in Sample 2.62, the Create method is invoked from the Win32_Service class instance (line 219 and lines 222 through 233), since it is a static method. Even if the method requires 12 parameters, not all of them must be given. For instance, the following command line is sufficient to create a Windows service:

 C:\>WMIServices.Wsf /Action:Create /Name:"MySNMP" /DisplayName:"My SNMP Service"                     /PathName:"J:\WINDOWS\System32\snmp.exe" /ServiceType:16                     /ErrorControl:1 /StartMode:"Manual" Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Service name 'MySNMP' created (0). 

Sample 2.62: Creating a Win32_Service instance (Part III)

start example

 ...: ...: ...: 216: 217:    ' -- CREATE ------------------------------------------------------------------------- 218:    If boolCreate = True Then 219:       Set objWMIClass = objWMIServices.Get (cWMIClass) ...: 222:       intRC = objWMIClass.Create (strServiceName, _ 223:                                   strDisplayName, _ 224:                                   strPathName, _ 225:                                   intServiceType, _ 226:                                   intErrorControl, _ 227:                                   strStartMode, _ 228:                                   boolDesktopInteract, _ 229:                                   strStartName, _ 230:                                   strStartPassword, _ 231:                                   strLoadOrderGroup, _ 232:                                   arrayLoadOrderGroupDependencies, _ 233:                                   arrayServiceDependencies) 234: 235:       WScript.Echo "Service name '" & strServiceName & "' created (" & intRC & ")." ...: 238:    End If 239: ...: ...: ...: 

end example

Note the value specified with the /ServiceType switch. This value defines the service type to be created (see Table 2.27). The code that corresponds to the previous output is shown in Sample 2.62.

To update an existing Windows service, the corresponding Windows service instance must be retrieved (line 242). Once retrieved, the Change method can be invoked (lines 24$ through 25$). This method requires 11 parameters, one less than the Create method. This makes sense, since the service name is not required by the method anymore. However, the service name is used to retrieve the Windows service instance (line 242).

Sample 2.63: Modifying a Win32_Service instance (Part IV)

start example

 ...: ...: ...: 239: 240:    ' -- UPDATE ------------------------------------------------------------------------- 241:    If boolUpdate = True Then 242:       Set objWMIInstance = objWMIServices.Get (cWMIClass & ".Name='" & strServiceName & "'") ...: 245:       intRC = objWMIInstance.Change (strDisplayName, _ 246:                                      strPathName, _ 247:                                      intServiceType, _ 248:                                      intErrorControl, _ 249:                                      strStartMode, _ 250:                                      boolDesktopInteract, _ 251:                                      strStartName, _ 252:                                      strStartPassword, _ 253:                                      strLoadOrderGroup, _ 254:                                      arrayLoadOrderGroupDependencies, _ 255:                                      arrayServiceDependencies) 256: 257:       WScript.Echo "Service name '" & strServiceName & "' updated (" & intRC & ")." ...: 260:    End If 261: ...: ...: ...: 

end example

Last but not least, if we are able to create Windows services, we should be able to delete Windows service instances. This operation is probably the easiest one to implement. After retrieving the Windows service instance to be deleted (line 264), the Delete method is invoked. Note that the Delete method invoked is the one defined at the level of the Win32_BaseService class and not the one defined at the level of the created SWBemObject (called Delete_). Invoking the deletion from the SWBemObject could also work, but since the class exposes a specific method for it, it is best to use the class method. The SWBemObject method is generic for the deletion of any instance represented by an SWBemObject. The methods implemented at the level of the class are specific to the object represented by the class. (See Sample 2.64.)

Sample 2.64: Deleting a Win32_Service instance (Part V)

start example

 ...: ...: ...: 261: 262:    ' -- DELETE ------------------------------------------------------------------------- 263:    If boolDelete = True Then 264:       Set objWMIInstance = objWMIServices.Get (cWMIClass & ".Name='" & strServiceName & "'") ...: 267:       intRC = objWMIInstance.Delete 268: 269:       WScript.Echo "Service name '" & strServiceName & "' deleted (" & intRC & ")." ...: 272:    End If ...: 276:    ]]> 277:    </script> 278:  </job> 279:</package> 

end example

2.4.13 Share classes

The share classes category represents details of shared resources, such as printers and folders. This category includes the classes listed in Table 2.28.

Table 2.28: The Share Classes

Name

Type

Description

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_Share

Dynamic

Represents a shared resource on a Windows system.

Win32_ConnectionShare

Association

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

Win32_PrinterShare

Association

Relates a local printer and the share that represents it as it is viewed over a network.

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_SessionProcess

Association

Represents an association between a logon session and the processes associated with that session.

Win32_ShareToDirectory

Association

Relates a shared resource on the computer system and the directory to which it is mapped.

The Win32_Share class also exposes methods to create, update, and delete shares. Performing these operations with shares is no more complicated than viewing, creating, updating, and deleting Windows services. Although there is no common point between a share and a Windows service, the WMI abstraction of these two real-world entities makes the scripting technique very similar. The Win32_Share class methods are called Create, SetShareInfo, and Delete. Sample 2.65 shows how to script with the Win32_Share class. Its command-line parameters are as follows:

 C:\>WMIShares.Wsf Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. Usage: WMIShares.wsf [ShareName] /Action:value /ShareType:value [/ShareAdmin[+|-]]                      [/MaximumAllowed:value] [/Description:value] [/SharePassword:value]                      [/Machine:value] [/User:value] [/Password:value] Options: ShareName      : The share name with its physical path. Action         : Specify the operation to perform: [list] or [create] or [update] or [delete]. ShareType      : Specify the share type: [Disk], [PrintQ], [Device] or [IPC]. ShareAdmin     : Specify if the share is an admin share. MaximumAllowed : Specify the maximum number of simultaneous connections. Description    : Specify the description for the share. SharePassword  : Specify the password for the share. 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) Example:       WMIShare.wsf /Action:List       WMIShare.wsf MyShare=C:\MyDirectory /ShareType:Disk /MaximumAllowed:10                    /Description:"This is my share" /Action:Create       WMIShare.wsf MyOtherShare=C:\MyOtherDirectory /ShareType:Disk /MaximumAllowed:1                    /ShareAdmin+ /Action:Create       WMIShare.wsf MyOtherShare=C:\MyOtherDirectory /ShareType:Disk /MaximumAllowed:5                    /Description:"This is my admin share" /Action:Update       WMIShare.wsf MyPrinterShare="My Printer,LocalsplOnly" /ShareType:PrintQ /Action:Create       WMIShare.wsf MyShare /Action:Delete 

Sample 2.65: Viewing, creating, updating, and deleting shares

start example

  1:<?xml version="1.0"?>  .:  8:<package>  9:<job>  ..:  13:    <runtime>  ..:  33:    </runtime>  34:  35:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DecodeShareTypeFunction.vbs" />  36:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" />  37:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  38:  39:    <object prog  reference="true"/>  40:    <object prog  />  41:  42:    <script language="VBscript">  43:    <![CDATA[  ..:  47:    Const cComputerName = "LocalHost"  48:    Const cWMINameSpace = "root/cimv2"  49:    Const cWMIClass = "Win32_Share"  ..:  79:    ' --------------------------------------------------------------------------------  80:    ' Parse the command line parameters  81:    If WScript.Arguments.Named.Count Then  82:       Select Case Ucase(WScript.Arguments.Named("Action"))  83:              Case "LIST"  84:                   boolList = True  85:              Case "CREATE"  86:                   boolCreate = True  87:              Case "UPDATE"  88:                   boolUpdate = True  89:              Case "DELETE"  90:                   boolDelete = True  91:              Case Else  92:                   WScript.Echo "Invalid action type. Only [List], [Create]..." & vbCRLF  93:                   WScript.Arguments.ShowUsage()  94:                   WScript.Quit  95:       End Select ...: ...: 151:    strComputerName = WScript.Arguments.Named("Machine") 152:    If Len(strComputerName) = 0 Then strComputerName = cComputerName 153: 154:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 155:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 156: 157:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _ 158:                                                     strUserID, strPassword) ...: 161:    ' -- LIST --------------------------------------------------------------------------- 162:    If boolList = True Then 163:       Set objWMIInstances = objWMIServices.InstancesOf (cWMIClass) 164: 165:       For Each objWMIInstance In objWMIInstances 166:           WScript.Echo "- " & Ucase (objWMIInstance.Name) & " " & String (60, "-") 167:           Set objWMIPropertySet = objWMIInstance.Properties_ 168:           For Each objWMIProperty In objWMIPropertySet 169:               Select Case objWMIProperty.Name 170:                      Case "Type" 171:                           DisplayFormattedProperty objWMIInstance, _ 172:                                                    objWMIProperty.Name, _ 173:                                                    ShareType (objWMIProperty.Value), _ 174:                                                    Null 175: 176:                      Case Else 177:                           DisplayFormattedProperty objWMIInstance, _ 178:                                                    objWMIProperty.Name, _ 179:                                                    objWMIProperty.Name, _ 180:                                                    Null 181:               End Select 182:           Next 183:           Set objWMIPropertySet = Nothing 184:           WScript.Echo 185:       Next 186: 187:       WScript.Echo vbCRLF & "Completed." ...: 190:    End If 191: 192:    ' -- CREATE ------------------------------------------------------------------------- 193:    If boolCreate = True Then 194:       Set objWMIClass = objWMIServices.Get (cWMIClass) 195:       If Err.Number Then ErrorHandler (Err) 196: 197:       intRC = objWMIClass.Create (strSharePath, _ 198:                                   strShareName, _ 199:                                   intShareType, _ 200:                                   intMaximumAllowed, _ 201:                                   strDescription, _ 202:                                   strSharePassword, _ 203:                                   Null) 204: 205:       WScript.Echo "Share name '" & strShareName & "' created (" & intRC & ")." ...: 208:    End If 209: 210:    ' -- UPDATE ------------------------------------------------------------------------- 211:    If boolUpdate = True Then 212:       Set objWMIInstance = objWMIServices.Get (cWMIClass & ".Name='" & strShareName & "'") 213:       If Err.Number Then ErrorHandler (Err) 214: 215:       intRC = objWMIInstance.SetShareInfo (intMaximumAllowed, _ 216:                                            strDescription, _ 217:                                            Null) 218: 219:       WScript.Echo "Share name '" & strShareName & "' updated (" & intRC & ")." ...: 222:    End If 223: 224:    ' -- DELETE ------------------------------------------------------------------------- 225:    If boolDelete = True Then 226:       Set objWMIInstance = objWMIServices.Get (cWMIClass & ".Name='" & strShareName & "'") 227:       If Err.Number Then ErrorHandler (Err) 228: 229:       intRC = objWMIInstance.Delete 230: 231:       WScript.Echo "Share name '" & strShareName & "' deleted (" & intRC & ")." ...: 234:    End If ...: 238:    ]]> 239:    </script> 240:  </job> 241:</package> 

end example

To create a share, seven parameters are required. Most of them are easy to understand, based on Sample 2.65. The only unusual parameter is the the ShareType parameter. Its values are shown in Table 2.29.

Table 2.29: The "ShareType" Values

Value

Description

0

Disk Drive

1

Print Queue

2

Device

3

IPC

0x80000000

Disk Drive Admin

0x80000001

Print Queue Admin

0x80000002

Device Admin

0x80000003

IPC Admin

Sample 2.65 is structured and uses the same logic as Samples 2.60 through 2.64 ("Creating, updating, and deleting a Win32_Service").

In the share classes category, there are also two interesting classes to consider: Win32_ServerConnection and Win32_ServerSession. These two classes are supported by the Session provider (discussed in the next chapter) and allow the review of the current connections (Win32_ServerConnection) and sessions (Win32_ServerSession) established with a server. The instances of these classes can be enumerated and deleted as well. Last but not least, with the Win32_Share class, it is possible to define the security on a share by using the SetShareInfo method and its Access parameter. This will be examined in Chapter 4, "WMI Security Scripting."

2.4.14 Start menu classes

The start menu classes category represents program groups from the start menu. The classes in this category are listed in Table 2.30.

Table 2.30: The Start Menu Classes

Name

Type

Description

Win32_LogicalProgramGroup

Dynamic

Represents a program group in a Windows system.

Win32_LogicalProgramGroupItem

Dynamic

Represents an element contained by a Win32_ProgramGroup Dynamic that is not itself another Win32_ProgramGroup Dynamic.

Win32_ProgramGroup

Dynamic

Deprecated.

Win32_ProgramGroupOrItem

Dynamic

Represents a logical grouping of programs on the user's Start|Programs menu.

Win32_UserAccount

Dynamic

Represents information about a user account on a Windows system.

Win32_LogicalProgramGroupDirectory

Association

Relates logical program groups (groupings in the start menu) and the file directories in which the are stored.

Win32_LogicalProgramGroupItemDataFile

Association

Relates the program group items of the start menu and the files in which the are stored.

Win32_ProgramGroupContents

Association

Relates a program group order and an individual program group or item contained in it.

The use of these classes is strictly limited to a read-only mode. For instance, currently the WMI providers do not support the creation of a Win32_LogicalProgramGroup instance to create a new "Start Menu" group. Figure 2.19 shows the associations that are in place for the Win32_LogicalProgramGroup class.

click to expand
Figure 2.19: The associations of the Win32_LogicalProgramGroup class.

Figure 2.19 shows that the Win32_LogicalProgramGroup class is associated with the Win32_LogicalProgramGroupOrItem class. Actually, the Win32_LogicalProgramGroupOrItem class is a superclass for the Win32_ LogicalProgramGroupItem class and the Win32_LogicalProgramGroup class (Figure 2.20).


Figure 2.20: The Win32_LogicalProgramGroupOrItem superclass.

A group in the "Start Menu" may contain a shortcut (Win32_LogicalProgramGroupItem) or another group (Win32_LogicalProgramGroup).

2.4.15 User account classes

The user account classes category represents user account information, such as group membership details. The classes in this category are listed in Table 2.31.

Table 2.31: The User Account Classes

Name

Type

Description

Win32_Account

Dynamic

Represents information about user accounts and group accounts known to the Windows system.

Win32_Group

Dynamic

Represents data about a group account.

Win32_LogonSession

Dynamic

Describes the logon session or sessions associated with a user logged on to Windows NT or Windows 2000.

Win32_LogonSessionMappedDisk

Dynamic

Represents the mapped logical disks associated with the session.

Win32_NetworkLoginProfile

Dynamic

Represents the network login information of a particular user on a Windows system.

Win32_SystemAccount

Dynamic

Represents a system account.

Win32_UserAccount

Dynamic

Represents information about a user account on a Windows system.

Win32_GroupInDomain

Association

Identifies the group accounts associated with a Windows NT domain.

Win32_GroupUser

Association

Relates a group and an account that is a member of that group.

Win32_UserInDomain

Association

Relates a user account and a Windows NT domain.

To retrieve information about user accounts and groups, it is possible to use the Win32_Account. This class is used as a superclass for three other classes: Win32_UserAccount, Win32_SystemAccount, and Win32_Group.

The Win32_UserAccount and Win32_Group classes expose a rename method, which allows the rename of a Windows account. To show an example of information available from the Win32_UserAccount class, by reusing Sample 1.5 ("Listing all instances of a class with their properties formatted"), we obtain the following output:

   1:    C:\>GetCollectionOfinstances Win32_Account   2:    Microsoft (R) Windows Script Host Version 5.6   3:    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.   4:   5:   6:    Caption: ................................. XP-DPEN6400\Administrators   7:    Description: ............................. Administrators have complete ...   8:    *Domain: ................................. XP-DPEN6400   9:    LocalAccount: ............................ TRUE  10:    *Name: ................................... Administrators  11:    SID: ..................................... S-1-5-32-544  12:    SIDType: ................................. 4  13:    Status: .................................. OK  14: ...: ...: ...: 222:    Caption: ................................. LISSWARENET\Domain Users 223:    Description: ............................. All domain users 224:    *Domain: ................................. LISSWARENET 225:    LocalAccount: ............................ FALSE 226:    *Name: ................................... Domain Users 227:    SID: ..................................... S-1-5-21-2025429265-507921405-1202660629-513 228:    SIDType: ................................. 2 229:    Status: .................................. OK ...: ...: ...: 609:    AccountType: ............................. 512 610:    Caption: ................................. LISSWARENET\alain.lissoir 611:    Description: ............................. 612:    Disabled: ................................ FALSE 613:    *Domain: ................................. LISSWARENET 614:    FullName: ................................ LISSOIR Alain 615:    LocalAccount: ............................ FALSE 616:    Lockout: ................................. FALSE 617:    *Name: ................................... alain.lissoir 618:    PasswordChangeable: ...................... TRUE 619:    PasswordExpires: ......................... FALSE 620:    PasswordRequired: ........................ TRUE 621:    SID: ..................................... S-1-5-21-2025429265-507921405-1202660629-1140 622:    SIDType: ................................. 1 623:    Status: .................................. OK ...: ...: ...: 

Because the Win32_Account class is associated with the Win32_Group class, it is possible to retrieve the user group membership. In the same way, from a Win32_Group instance, it is possible to retrieve members of a group by using the associations in place. Figure 2.21 shows the associations available for Win32_Group class.

click to expand
Figure 2.21: The Win32_Group class associations.

Figure 2.22 shows an example of existing associations for a particular user.

click to expand
Figure 2.22: Associated instances of one group.

We can benefit from these relationships by using a specific WQL Query. In the first book, Understanding WMI Scripting, we saw how to retrieve miscellaneous associations from classes and instances with WQL, and we put that in practice with some sample scripts in this chapter (e.g., Samples 2.4 through 2.7, "Retrieving hardware resource information"). For example, from an "Enterprise Admins" group instance, if we want to retrieve the members of the group, we must use the following WQL query:

 Associators of {Win32_Group.Domain='LISSWARENET',Name='Enterprise Admins'}                               Where AssocClass=Win32_GroupUser Role=GroupComponent 

In the same way, to retrieve the inclusion of the "Enterprise Admins" group in any other group (MemberOf), we must use the following WQL query:

 Associators of {Win32_Group.Domain='LISSWARENET',Name='Enterprise Admins'}                                Where AssocClass=Win32_GroupUser Role=PartComponent 

Sample 2.66 implements these two WQL queries in a script. This script requests a group name as a command-line parameter. Once started, the script retrieves the group instance (lines 73 and 74) and displays its properties (lines 82 through 92). Next, based on the Win32_Group associations, the script retrieves the group membership information. At line 99 through 103, we recognize the first WQL query (Members) and at line 118 through 122, we recognize the second WQL query (MemberOf).

Sample 2.66: Retrieving the group membership

start example

   1:<?xml version="1.0"?>   .:   8:<package>   9:  <job>  ..:  13:    <runtime>  ..:  19:    </runtime>  20:  21:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\DisplayFormattedPropertyFunction.vbs" />  22:    <script language="VBScript" src="/books/2/679/1/html/2/..\Functions\TinyErrorHandler.vbs" />  23:  24:    <object prog  reference="true"/>  25:    <object prog  />  26:  27:    <script language="VBscript">  28:    <![CDATA[  ..:  32:    Const cComputerName = "LocalHost"  33:    Const cWMINameSpace = "root/cimv2"  ..:  47:    ' --------------------------------------------------------------------------------  48:    ' Parse the command line parameters  49:    If WScript.Arguments.UnNamed.Count = 0 Then  50:       WScript.Arguments.ShowUsage()  51:       WScript.Quit  52:    End If  53:  54:    strGroupName = WScript.Arguments.UnNamed(0)  ..:  65:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault  66:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate  67:  68:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, cWMINameSpace, _  69:                                                     strUserID, strPassword)  ..:  72:    ' ----------------------------------------------------------------------------------------  73:    Set objWMIInstances = objWMIServices.ExecQuery ("Select * From Win32_Group " & _  74:                                                    "Where Name='" & strGroupName & "'")  ..:  77:    If objWMIInstances.Count Then  78:       For Each objWMIInstance In objWMIInstances  79:           WScript.Echo "- '" & Ucase (objWMIInstance.Domain) & "\" & _  80:                        objWMIInstance.Name & "' " & String (60, "-")  81:           Set objWMIPropertySet = objWMIInstance.Properties_  82:           For Each objWMIProperty In objWMIPropertySet  83:               Select Case objWMIProperty.Name  84:                      Case ""  85:  86:                      Case Else  87:                           DisplayFormattedProperty objWMIInstance, _  88:                                                    objWMIProperty.Name, _  89:                                                    objWMIProperty.Name, _  90:                                                    Null  91:               End Select  92:           Next  93:           WScript.Echo ...:  97:           'Members ------------------------------------------------------------------------  98:           WScript.Echo " - Members: " & String (60, "-")  99:           Set objAssocInstances = objWMIServices.ExecQuery _ 100:                                    ("Associators of {Win32_Group.Domain='" & _ 101:                                    objWMIInstance.Domain & "',Name='" & _ 102:                                    objWMIInstance.Name & _ 103:                                    "'} Where AssocClass=Win32_GroupUser Role=GroupComponent") 104: 105:           If objAssocInstances.Count Then 106:              For Each objAssocInstance In objAssocInstances 107:                  WScript.Echo " " & objAssocInstance.Domain & "\" & objAssocInstance.Name 108:              Next 109:           Else 110:              WScript.Echo " No 'Members' available." 111:           End If 112:           WScript.Echo ...: 116:           'MemberOf ------------------------------------------------------------------------ 117:           WScript.Echo " - MemberOf: " & String (60, "-") 118:           Set objAssocInstances = objWMIServices.ExecQuery _ 119:                                    ("Associators of {Win32_Group.Domain='" & _ 120:                                    objWMIInstance.Domain & "',Name='" & _ 121:                                    objWMIInstance.Name & _ 122:                                    "'} Where AssocClass=Win32_GroupUser Role=PartComponent") 123: 124:           If objAssocInstances.Count Then 125:              For Each objAssocInstance In objAssocInstances 126:                  WScript.Echo " " & objAssocInstance.Domain & "\" & objAssocInstance.Name 127:              Next 128:           Else 129:              WScript.Echo " No 'memberOf' available." 130:           End If 131:           WScript.Echo ...: 134:       Next 135: 136:       WScript.Echo "Completed." ...: 139:    Else 140:       WScript.Echo "No group available." 141:    End If 142:    WScript.Echo ...: 147:    ]]> 148:    </script> 149:  </job> 150:</package> 

end example

Once executed, we obtain the following output:

 C:\>GetGroupInfo "Enterprise Admins" Microsoft (R) Windows Script Host Version 5.6 Copyright (C) Microsoft Corporation 1996-2001. All rights reserved. - 'LISSWARENET\Enterprise Admins' ------------------------------------------------------------ Caption: ................................. LISSWARENET\Enterprise Admins Description: ............................. Designated administrators of the enterprise *Domain: ................................. LISSWARENET LocalAccount: ............................ FALSE *Name: ................................... Enterprise Admins SID: ..................................... S-1-5-21-2025429265-507921405-1202660629-519 SIDType: ................................. 2 Status: .................................. OK   - Members: ------------------------------------------------------------   LISSWARENET\Administrator   LISSWARENET\alain.lissoir   - MemberOf: ------------------------------------------------------------   XP-DPEN6400\Administrators Completed. 

Another useful and immediate application of the Win32_UserAccount class is the conversion of the user name to a SID and vice versa. The principle is very simple. It consists of a WQL data query. To retrieve the SID from the UserID, the following WQL query can be used:

 Select SID From Win32_Account Where Name='Alain.Lissoir' 

Sample 2.67 is a function making use of this WQL data query. This function is called GetSIDFromUserID() and can perform a WMI connection (lines 16 through 20) with a specific set of credentials.

Sample 2.67: Retrieving the SID from the UserID

start example

  .:  .:  .:  8:'------------------------------------------------------------------------------------------  9:Function GetSIDFromUserID (strUserAccount, strComputerName, strUserID, strPassword) ..: 16:    objWMILocator. Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 17:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 18: 19:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, "Root\CIMv2", _ 20:                                                     strUserID, strPassword) ..: 23:    Set objWMIInstances = objWMIServices.ExecQuery ("Select SID From Win32_Account Where" & _ 24:                                                    "Name='" & strUserAccount & "'") ..: 27:    If objWMIInstances.Count = 1 Then 28:       For Each objWMIInstance In objWMIInstances 29:           GetSIDFromUserID = objWMIInstance.SID 30:       Next 31:    Else 32:           GetSIDFromUserID = "" 33:    End If ..: 39:End Function 

end example

The WMI connection with a set of different credentials is not mandatory to retrieve the SID; however, this makes the function totally independent of the caller context. The only required parameters are the system and the credentials to use for the WMI connection with the UserID to be resolved as a SID (line 9). Next, the routine makes use of the ExecQuery method of the SWBemServices object to run the WQL data query (lines 23 and 24). Since a query always returns a collection, the routine expects to have one instance of the Win32_UserAccount class stored in a collection (line 27) and extracts the SID from the SID property accordingly (line 29).

To retrieve the UserID from the SID, the following WQL query can be used:

 Select Name From Win32_Account Where SID='S-1-5-21-1935655697-839522115-1708537768-1003' 

Sample 2.68 uses the exact same logic as Sample 2.67, but, instead, it accepts a SID as a parameter and returns a UserID as a result.

Sample 2.68: Retrieving the UserID from the SID

start example

  .:  .:  .:  8:' -------------------------------------------------------------------------------------  9:Function GetUserIDFromSID (strSID, strComputerName, strUserID, strPassword) ..: 16:    objWMILocator.Security_.AuthenticationLevel = wbemAuthenticationLevelDefault 17:    objWMILocator.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate 18: 19:    Set objWMIServices = objWMILocator.ConnectServer(strComputerName, "Root\CIMv2", _ 20:                                                     strUserID, strPassword) ..: 23:    Set objWMIInstances = objWMIServices.ExecQuery ("Select Name From Win32_Account" & _ 24:                                                    "Where SID='" & strSID & "'") ..: 27:    If objWMIInstances.Count = 1 Then 28:       For Each objWMIInstance In objWMIInstances 29:           GetUserIDFromSID = objWMIInstance.Name 30:       Next 31:    Else 32:           GetUserIDFromSID = "" 33:    End If ..: 39:End Function 

end example




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