Part 8: Using Advanced Scripting Techniques to Manage Networks

In addition to the functionality offered by Win32_NetworkAdapterConfiguration and similar classes, WMI contains other classes that can be useful for managing network clients. This section provides advanced scripting techniques, including scripting steps and sample scripts, for these tasks:

  • Coordinating system time across a network.

    Several classes enable you to coordinate system dates and times by using scripts.

  • Changing networking settings in the registry.

    The Windows registry, including all its settings, is accessible to scripting by using the System Registry WMI provider.

You can also use these advanced scripting techniques to script other areas of system administration besides TCP/IP networking.

On This Page

Coordinating System Time Across a Network
Changing Networking Settings in the Registry
Tools for Network Management with Advanced Scripting Techniques

Coordinating System Time Across a Network

Some operating system features and client/server applications depend on synchronized dates and time among computers on a network. For example, comparisons of the time stamps of files or events on different computers produce reliable data only if the computers’ system times match.

caution.gif  Caution
Active Directory automatically synchronizes dates and times for computers that have accounts in the directory service. Do not change the date and time of a computer that is joined to an Active Directory domain.

Rather than concentrating date and time functionality in one or two classes, WMI distributes it among several classes, some of which are more general containers:

  • Win32_ComputerSystem and Win32_OperatingSystem both include, among many others, properties and methods that can manage date and time settings.

  • Win32_TimeZone, Win32_CurrentTime, Win32_LocalTime, and Win32_UTCTime (the latter three are new for Windows XP) also contain read-only properties that expose each component of the date and time, time zone, and daylight time setting.

  • The WMI Scripting Library SwbemDateTime object, which is new in Windows XP, can also be used to manipulate date and time objects together with the other classes.

Win32_OperatingSystem

Table 39 describes the read-only properties that the Win32_OperatingSystem class provides for managing date and time settings.

Table 39   Win32_OperatingSystem Date & Time Properties

Property

Type

Description

CurrentTimeZone

(read-only)

sint16

Number of minutes that an operating system is offset from Greenwich Mean Time (GMT). The number can be positive, negative, or zero.

LocalDateTime

(read-only)

datetime

Operating system's version of the local date and time of day.

Table 40 describes the Win32_OperatingSystem method for managing date and time settings.

Table 40   Win32_OperatingSystem Date & Time Method

Method

Parameters

Description

SetDateTime

LocalDateTime – datetime

Value of the current time.

Sets the current system time on the computer. The calling process must have the SE_SYSTEMTIME_NAME privilege.

This method returns a positive integer:

  • 0 indicates successful completion.

  • Numbers greater than 0 indicate an error.

Win32_ComputerSystem

Table 41 describes the Win32_ComputerSystem properties, two of which are read/write, for managing date and time settings.

Table 41   Win32_ComputerSystem Date & Time Properties

Property

Type

Description

CurrentTimeZone

(read/write)

sint16

Unit: Minutes

Amount of time the unitary computer system is offset from Coordinated Universal Time (UTC).

DaylightInEffect

(read-only)

Boolean

Daylight savings mode is ON.

EnableDaylightSavingsTime

(read/write)

In Windows XP and Windows Server 2003 only

Boolean

Enables daylight saving time (DST) on a computer. A value of true indicates that the system time changes to an hour ahead or behind when DST starts or ends. A value of false indicates that the system time does not change to an hour ahead or behind when DST starts or ends. A value of NULL indicates that the DST status is unknown on a system.

Win32_TimeZone

Win32_TimeZone represents the time zone information for a Windows system, which includes changes needed for the daylight saving time transition. This class includes several properties, all read-only, but no methods. The properties include components of the date and time for standard and daylight time and the bias between them.

Win32_CurrentTime

Use Win32_LocalTime or Win32_UTCTime rather than this class.

New for Windows XP and Windows Server 2003

An abstract singleton class, which does not have instances, Win32_CurrentTime serves as a template for the other time classes. It describes a point in time by using the component items such as seconds, minutes, hours, days, days of the week, week in the month, months, quarters, and years. Note that although the SDK shows a Milliseconds property for this class, it is not actually implemented.

Win32_LocalTime and Win32_UTCTime both inherit from Win32_CurrentTime.

Win32_LocalTime

New for Windows XP and Windows Server 2003

The Win32_LocalTime class represents the local time on the computer. It inherits from Win32_CurrentTime and exposes the same properties. The Hour property returns the local time on a 24-hour clock. Note that although the SDK shows a Milliseconds property for this class, it is not actually implemented.

Win32_UTCTime

New for Windows XP and Windows Server 2003

The Win32_UTCTime class represents the local time on the computer. It inherits from Win32_CurrentTime and exposes the same properties. The Hour property returns Coordinated Universal Time (UTC) on a 24–hour clock. Note that although the SDK shows a Milliseconds property for this class, it is not actually implemented.

WMI Scripting Library SwbemDateTime Object

New for Windows XP and Windows Server 2003

This helper object parses and converts WMI datetime values (for example, the LocalDateTime property of Win32_OperatingSystem) to and from other formats. For more information, see “SWbemDateTime” in the WMI SDK at https://go.microsoft.com/fwlink/?LinkId=29997.

VBScript Now Function

This function extracts the current system date and time from the computer running the script.

Retrieving the Current Time by Using the VBScript Now Function

This script retrieves the current system time on a computer by using the VBScript Now function.

Listing 52   Time-get.vbs

  
1

WScript.Echo "Current Date and Time: " & Now

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>time-get.vbs

Current Date and Time: 5/19/2004 2:46:29 PM

Retrieving the Local Time by Using WMI

WMI provides a less simple but more flexible way than the VBScript Now function to read the local date and time. The Win32_LocalTime class exposes properties representing the year, quarter, month, week in month, date, day of week, hour (based on a 24-hour clock), minute, and second of local system time.

Scripting Steps

Listing 53 retrieves the local time on a computer with the WMI Win32_LocalTime class. This class is new for Windows XP, so the script runs only against Windows XP and Windows Server 2003.

  1. Create a variable and assign the name of a computer to it. For the local computer, simply specify "." as the computer name. To run this script remotely, specify the name of an accessible remote computer on your network on which you have administrative privileges. The name can be in the form of either a host name or an IP address.

  2. Use a GetObject call to connect to the WMI namespace root\cimv2, and set the impersonation level to “impersonate.”

  3. Use the ExecQuery method to query the Win32_LocalTime class.

    This returns a collection consisting of one object representing the local time on the computer.

  4. Use the properties of the local time object to display the month, day, year, quarter, week in the month, day of the week and time.

Listing 53   Time-get-local.vbs

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

On Error Resume Next
 
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
 & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colLocalTimes = objWMIService.ExecQuery("Select * from Win32_LocalTime")
 
For Each objLocalTime in colLocalTimes
  Wscript.Echo "Date: " & objLocalTime.Month & "/" & objLocalTime.Day & _
   "/" & objLocalTime.Year
  Wscript.Echo "Quarter: " & objLocalTime.Quarter
  Wscript.Echo "Week In the Month: " & objLocalTime.WeekInMonth
  Wscript.Echo "Day Of the Week: " & objLocalTime.DayOfWeek
  Wscript.Echo "Time: " & objLocalTime.Hour & ":" & objLocalTime.Minute & _
   ":" & objLocalTime.Second
Next

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>time-get-local.vbs

Date: 5/19/2004

Quarter: 2

Week In the Month: 4

Day Of the Week: 3

Time: 16:55:39

Retrieving the UTC Time by Using WMI

The Greenwich Observatory in the United Kingdom keeps Coordinated Universal Time (UTC), which is the international standard time. UTC differs from local time by a differential for each local time zone, which is exposed by other classes discussed later in this section. In comparing system times of computers in different time zones, UTC can be useful because it is the current time at the Greenwich Observatory and thus has the same value anywhere in the world.

Scripting Steps

Listing 54 retrieves current UTC on a computer by using the WMI Win32_UTCTime class. Like Win32_LocalTime, in Win32_UTCTime the hour uses a 24-hour clock. This class is new for Windows XP, so the script runs only against Windows XP and Windows Server 2003.

  1. Create a variable to specify the computer name.

  2. Use a GetObject call to connect to the WMI namespace root\cimv2, and set the impersonation level to “impersonate.”

  3. Use the ExecQuery method to query the Win32_UTCTime class.

    This returns a collection consisting of one object representing the UTC according to this computer.

  4. Use the properties of the UTC object to display the month, day, year, quarter, week in the month, day of the week and time.

Listing 54   Time-get-utc.vbs

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

On Error Resume Next
 
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
 & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colUTCTimes = objWMIService.ExecQuery("Select * from Win32_UTCTime")
 
For Each objUTCTime in colUTCTimes
  Wscript.Echo "Date: " & objUTCTime.Month & "/" & objUTCTime.Day & _
   "/" & objUTCTime.Year
  Wscript.Echo "Quarter: " & objUTCTime.Quarter
  Wscript.Echo "Week In the Month: " & objUTCTime.WeekInMonth
  Wscript.Echo "Day Of the Week: " & objUTCTime.DayOfWeek
  Wscript.Echo "Time: " & objUTCTime.Hour & ":" & objUTCTime.Minute & _
   ":" & objUTCTime.Second
Next

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>time-get-utc.vbs

Date: 5/19/2004

Quarter: 2

Week In the Month: 4

Day Of the Week: 3

Time: 23:56:29

Retrieving the Time from a Remote Computer

As with other WMI classes, to get UTC or local time from a remote computer, simply change the name of the computer in strComputer (see line 3 of the script) to a remote computer on which you have administrative credentials and WMI handles the details for you.

Comparing Local Times on Two Computers

One way to compare system dates and times on two computers in the same time zone is provided by the LocalDateTime property of the Win32_OperatingSystem class. This read-only property returns the operating system’s setting for the local date and time, including the offset from Greenwich Mean Time, indicating the time zone. This approach works on networks that contain computers that run operating systems older than Windows XP and Windows Server 2003.

To compare dates and times on computers in different time zones, you can adapt this script to compensate for time zones by calculating and applying the difference between the last four digits of the datetime value returned by LocalDateTime. These digits begin with a positive or negative sign and a three-digit offset indicating the number of minutes that the local time zone deviates from UTC.

Optionally, you can compare the dates and times returned by Win32_UTCTime. These dates and times are the same on two synchronized computers regardless of local time zone. However, this class is new to Windows XP and Windows Server 2003.

Scripting Steps

Listing 55 compares dates and times on two computers, either a local and a remote computer or two remote computers.

  1. Create variables to specify the names of the two computers.

  2. On each of the two computers, use a GetObject call to connect to the WMI namespace root\cimv2, and set the impersonation level to “impersonate.”

  3. On each computer, use the ExecQuery method to query the Win32_OperatingSystem class.

    This returns two collections of operating system objects, with one object in each collection.

  4. After each of the ExecQuery calls returns, call the VBScript Now function and assign the seconds from each time to a variable.

    The Now function returns the system date and time at the moment it is run.

  5. If the difference between the two time variables is not 0, assign it to a variable. This represents the difference between the times that the two Win32_OperatingSystem queries finished executing.

    The time retrieved by the LocalDateTime property on each computer depends on the exact moment when the query executes.

  6. Loop through each operating system object in the collection on the first computer with For Each.

  7. Within the first For Each loop, loop through each operating system object in the collection on the second computer with a nested For Each loop.

  8. Use the LocalDateTime property to retrieve the local system time from the two computers.

  9. Truncate the datetime objects returned by LocalDateTime to the date, hour and minute values and, if there is any differential between the two Now values, use it to adjust the first time before comparing the two times.

  10. Call the WMIDateToString function to display the two adjusted system dates and times in more readable format.

    For more information about WMIDateToString, see “Displaying DHCP Client Information” earlier in this paper.

  11. Compare the two adjusted dates and times and output the results of the comparison.

    note.gif  Note
    The dates and times retrieved by those two collections are static after ExecQuery() runs. That is, they are a snapshot of the date and time at the moment the query ran. If the network connection is good and both computers are not busy, less than a second may separate the two queries, and it will not be necessary to compensate for latency. If more than a second has elapsed from the first Now function call to the second, the script compensates for the latency by adding the difference to the time retrieved from the first computer (line 28).

Listing 55   Time-compare.vbs

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

On Error Resume Next
 
strComputer1 = "."
strComputer2 = "server-d1"
Set objWMIService1 = GetObject("winmgmts:" _
 & "{impersonationLevel=impersonate}!\\" & strComputer1 & "\root\cimv2")
Set objWMIService2 = GetObject("winmgmts:" _
 & "{impersonationLevel=impersonate}!\\" & strComputer2 & "\root\cimv2")
 
Set colOSes1 = objWMIService1.ExecQuery("Select * from " & _
 "Win32_OperatingSystem")
strTime1 = Now
Set colOSes2 = objWMIService2.ExecQuery("Select * from " & _
 "Win32_OperatingSystem")
strTime2 = Now
intSeconds1 = CInt(Left(Right(strTime1, 5), 2))
intSeconds2 = CInt(Left(Right(strTime2, 5), 2))
intDiff = 0
If intSeconds1 <> intSeconds2 Then
  intDiff = intSeconds2 - intSeconds1
End If
 
For Each objOS1 in colOSes1
  For Each objOS2 in colOSes2
    intDateTime1 = Left(objOS1.LocalDateTime, 14)
    intDateTime2 = Left(objOS2.LocalDateTime, 14)
    If intDiff <> 0 Then
      intDateTime1 = intDateTime1 + intDiff
    End If
    WScript.Echo "Adjusted time on " & strComputer1 & ": " & _
     WMIDateToString(intDateTime1)
    WScript.Echo "Adjusted time on " & strComputer2 & ": " & _
     WMIDateToString(intDateTime2)
    If intDateTime1 = intDateTime2 Then
      Wscript.Echo "Dates and times are equal."
    Else
      Wscript.Echo "Dates and times are not equal."
    End If
  Next
Next
 
'******************************************************************************
 
Function WMIDateToString(dtmDate)
 
WMIDateToString = CDate(Mid(dtmDate, 5, 2) & "/" & _
                  Mid(dtmDate, 7, 2) & "/" & _
                  Left(dtmDate, 4) & " " & _
                  Mid(dtmDate, 9, 2) & ":" & _
                  Mid(dtmDate, 11, 2) & ":" & _
                  Mid(dtmDate, 13, 2))
 
End Function

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>time-compare.vbs

Adjusted time on .: 5/19/2004 5:01:26 PM

Adjusted time on server1: 5/19/2004 5:05:52 PM

Dates and times are not equal.

Setting the Time on One Computer by Using Command-Line Tools

Two command-line tools, Date.exe and Time.exe, allow you to set the local system date and time on a local computer:

  • Date.exe uses the following format:

    date date/month/year
    

    For example, the following command line sets the system date to March 8, 2004:

    date 03/08/2004
    

    When you run this command without arguments, it retrieves the current system date.

  • Time.exe uses the following format where hours:minutes is in 24-hour clock format:

    time hours:minutes
    

    For example, the following command line sets the system time to 6:25 p.m:

    time 18:25
    

    When you run this command without arguments, it retrieves the current system date.

Date.exe and Time.exe are available in all Windows operating systems.

The net time command provides options that enable you to synchronize time with a time server.

Setting the Time on One Computer by Using WMI

Using WMI, you can read and set times on remote as well as local computers. The WMI class Win32_OperatingSystem includes a read-only property, LocalDateTime, which returns the operating system’s setting for the local date and time, including the offset from Greenwich Mean Time indicating the time zone.

caution.gif  Caution
Active Directory automatically synchronizes dates and times for computers that have accounts in the directory service. Do not change the date and time of a computer that is joined to an Active Directory domain.

Win32_OperatingSystem also includes a method, SetDateTime(), which takes a date and time in the form of a DATETIME object as a parameter, and sets this as the computer's current date and time. SetDateTime() returns zero (0) to indicate success and any other number to indicate an error. To call SetDateTime(), the script must be running under credentials that have the SE_SYSTEMTIME_NAME privilege.

The following script uses the LocalDateTime property and the SetDateTime() method to set a new date and time for a local or remote computer.

The new date and time must be in DATETIME format, a WMI data type that is a fixed-length string representing a specific date and time in WMI. The string takes the form:

yyyymmddHHMMSS.mmmmmmsUUU

Table 42 describes the valid values for the DATETIME fields. All fields must match the field length indicated in the table; use leading zeros if needed.

Table 42   DATETIME Field Descriptions

Field

Description

yyyy

Four-digit year (0000–9999).

mm

Two-digit month (01–12).

dd

Two-digit day of the month (01–31). This value must be appropriate for the month. For example, February 31 is invalid. However, your implementation does not have to check for valid data.

HH

Two-digit hour of the day using the 24-hour clock (00–23).

MM

Two-digit minute in the hour (00–59).

SS

Two-digit number of seconds in the minute (00–59).

mmmmmm

Six-digit number of microseconds in the second (000000–999999).

s

Plus sign (+) or minus sign (–) to indicate a positive or negative offset from UTC.

UUU

Three-digit offset indicating the number of minutes that the originating time zone deviates from UTC. For WMI, it is encouraged, but not required, that you convert times to GMT (a UTC offset of zero).

You can use asterisks to indicate unused fields or as a wildcard value. For example, a date and time with an unspecified year can occur in any year, as in the following example:

0416***.****+

If you want to leave a field unspecified, you must replace the entire field with asterisks. The following examples illustrate valid and invalid uses of asterisks:

19980416******.000000+***      ' Valid
1998-04-16 ******:***        ' Invalid
199*0416******.000000+***      ' Invalid
199*-04-16 ******:***        ' Invalid

For more information about the DATETIME data type, see the WMI SDK topic "Date and Time Format," from which this explanation is adapted. For more information about how to work with dates and times in scripting, see the Windows 2000 Scripting Guide topics "Working with Dates and Times" in the "VBScript Primer" and "WMI Scripting Primer" chapters at https://go.microsoft.com/fwlink/?LinkId=30137 and https://go.microsoft.com/fwlink/?LinkId=30136.

Scripting Steps

Listing 56 sets the system time on a local or remote computer. This script illustrates how to use the SetDateTime method of Win32_OperatingSystem. However, the precision of this approach is typically limited to the minute, rather than the second, because it requires entering the correct time at the last moment.

  1. Create a variable and assign the name of a computer to it.

  2. Create a variable and assign a string (use WMI DATETIME format) representing the date and time you want to set. Just before running the script, replace the WMI DATETIME format with the actual time you want to set. The sample date in the script is equivalent to May 7, 2004, 5:01 p.m. with a negative offset of 8 hours (480 minutes) from GMT.

  3. Use a GetObject() call to connect to the WMI namespace root\cimv2, and set the impersonation level to “impersonate.”

  4. Call the ExecQuery method to query the Win32_OperatingSystem class.

    This returns a collection consisting of one object representing the operating system.

  5. For each operating system object in the collection, perform the following tasks.

  6. Call the SetDateTime method of Win32_OperatingSystem, passing it the datetime value.

  7. Check the return value of the method and display a success or error method.

  8. Requery Win32_OperatingSystem and get the refreshed LocalDateTime property reflecting the change.

  9. Call the WMIDateToString function to display the datetime value in more readable format. For more information about this function, see "Displaying DHCP Client Information" earlier in this paper.

Listing 56   Time-set.vbs

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

On Error Resume Next
 
strComputer = "."
dtmNewDateTime = "20040520151300.000000-480"
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate, " _
 & "(Systemtime)}!\\" & strComputer & "\root\cimv2")
Set colOSes = objWMIService.ExecQuery("SELECT * FROM Win32_OperatingSystem")
 
For Each objOS In colOSes
  intSet = objOS.SetDateTime(dtmNewDateTime)
  If intSet = 0 Then
    Wscript.Echo "Successfully set new date and time."
  Else
    Wscript.Echo "Unable to set mew date and time."
  End If
Next
 
Set colOSes = objWMIService.ExecQuery("SELECT * FROM Win32_OperatingSystem")
For Each objOS In colOSes
  Wscript.Echo "New date and time: " & WMIDateToString(objOS.LocalDateTime)
Next
 
'******************************************************************************
 
Function WMIDateToString(dtmDate)
WMIDateToString = CDate(Mid(dtmDate, 5, 2) & "/" & _
                  Mid(dtmDate, 7, 2) & "/" & _
                  Left(dtmDate, 4) & " " & _
                  Mid(dtmDate, 9, 2) & ":" & _
                  Mid(dtmDate, 11, 2) & ":" & _
                  Mid(dtmDate, 13, 2))
End Function

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>time-set.vbs

Successfully set new date and time.

New date and time: 5/20/2004 3:08:49 PM

Synchronizing Times on Two Computers

Running a network often requires that system times be synchronized across it. Some applications, such as those that compare files based on time stamps, require that times on different hosts agree closely.

More sophisticated methods of ensuring accurate and synchronized time across a network use tools that synchronize with public time servers. This section, however, shows how to use a simple script to compare times on two computers, and if they are not identical, to set the time on the target computer to agree with the reference computer. This approach assumes that you have already accessed an external source and manually set the correct time on the reference computer.

A more complex script might automate obtaining a reference time from an external source and then setting the target computers to it. Although WMI does not provide this functionality, you might be able to do it with a command-line tool or a Web application that is run through the WSH Exec method.

caution.gif  Caution
Active Directory automatically synchronizes dates and times for computers that have accounts in the directory service. Do not change the date and time of a computer that is joined to an Active Directory domain.

The net time command provides options that enable you to synchronize time by using a time server.

Scripting Steps

Listing 57 compares system time (compensated for time zone) on two computers, by using the LocalDateTime property of the Win32_OperatingSystem class. For each computer, the script takes the leftmost fourteen characters of LocalDateTime (the ones that indicate date and time down to the second) and compares the truncated string.

If the time on the first computer does not agree with the second, the script uses the SetDateTime() method of Win32_OperatingSystem to set the second computer to the time on the first. This takes into account daylight saving differences, because if the two computers are in the same time zone and the time is the same, the computers’ daylight saving time setting must also be the same.

When you use this script, the degree of precision for time synchronization is typically limited to the minute, rather than the second, because of network latency and the time necessary to execute code.

To carry out this task, the script must:

  1. Create variables to specify the names of the two computers.

  2. On each of the two computers, use a GetObject call to connect to the WMI namespace root\cimv2, and set the impersonation level to “impersonate.”

    Note that this script does not check for network connectivity to either computer.

  3. On each computer, use the ExecQuery method to query the Win32_OperatingSystem class.

    This returns two collections of operating system objects, with one object in each collection.

  4. After each of the ExecQuery calls returns, call the VBScript Now function and assign the seconds from each time to a variable.

    The Now function returns the system date and time at the moment it is run.

  5. Assign the difference between the two time variables to another variable, which represents the difference between the times that the two Win32_OperatingSystem queries were executed. The moment when each query runs determines the time that the LocalDateTime property retrieves for that computer.

  6. If the difference between the two time variables is not 0, assign it to a variable, which represents the difference between the times the two Win32_OperatingSystem queries finished executing.

    The time retrieved by the LocalDateTime property on each computer depends on the exact moment when the query executes.

  7. Loop through each operating system object in the collection on the first computer with For Each.

  8. Within the first For Each loop, loop through each operating system object in the collection on the second computer with a nested For Each loop.

  9. Use the LocalDateTime property to retrieve the local system time from the two computers.

  10. Assign the LocalDateTime property from the first (reference) computer to a variable that will be used to set the time on the second (target) computer if necessary.

  11. Truncate the datetime objects returned by LocalDateTime to the date, hour and minute values.

  12. If there is any differential between the two Now values, use it to adjust the reference time before comparing the two times.

  13. Compare the two adjusted dates and times.

  14. If the dates and times are equal, display a message.

  15. If the dates and times are not equal, call the SetDateTime method of Win32_OperatingSystem on the target computer.

  16. Check the return value of the method and display a success or error message.

Listing 57   Time-sync.vbs

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

On Error Resume Next
 
strComputer1 = "."
strComputer2 = "client1"
 
Set objWMIService1 = GetObject("winmgmts:" _
 & "{impersonationLevel=impersonate}!\\" & strComputer1 & "\root\cimv2")
Set objWMIService2 = GetObject("winmgmts:{impersonationLevel=impersonate, " _
 & "(Systemtime)}!\\" & strComputer2 & "\root\cimv2")
 
Set colOSes1 = objWMIService1.ExecQuery("SELECT * FROM Win32_OperatingSystem")
strTime1 = Now
Set colOSes2 = objWMIService2.ExecQuery("SELECT * FROM Win32_OperatingSystem")
strTime2 = Now
intSeconds1 = CInt(Left(Right(strTime1, 5), 2))
intSeconds2 = CInt(Left(Right(strTime2, 5), 2))
intDiff = 0
If intSeconds1 <> intSeconds2 Then
  intDiff = intSeconds2 - intSeconds1
End If
 
For Each objOS1 in colOSes1
  For Each objOS2 in colOSes2
    dtmRefDateTime = objOS1.LocalDateTime
    intDateTime1 = Left(dtmRefDateTime, 14)
    intDateTime2 = Left(objOS2.LocalDateTime, 14)
    If intDiff <> 0 Then
      intDateTime1 = intDateTime1 + intDiff
    End If
    If intDateTime1 = intDateTime2 Then
      Wscript.Echo "Dates and times on " & strComputer1 & " and " & _
       strComputer2 & "are equal."
    Else
      intSet = objOS2.SetDateTime(dtmRefDateTime)
      If intSet = 0 Then
        Wscript.Echo "Successfully synchronized date and time on " & _
         strComputer2 & " with reference (" & strComputer1 & ")."
      Else
        Wscript.Echo "Unable to set new date and time on " & strComputer2 & "."
      End If
    End If
  Next
Next

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>time-sync.vbs

Successfully synchronized date and time on client1 with reference (.).

Synchronizing Times on Multiple Computers

Extending the time comparison from two to any number of computers is relatively simple. The following script uses the same basic code as Time-sync.vbs. However, it gets a list of computers from an array and then iterates through each, comparing the system time to that of the reference computer, and if necessary, synchronizing them.

This script uses a rough algorithm for time comparison and synchronization, illustrating one way to synchronize computer times by using scripting. However, if network latency is too great, system times on computers synchronized with this approach may vary unacceptably from the reference time.

caution.gif  C aution
Active Directory automatically synchronizes dates and times for computers that have accounts in the directory service. Do not change the date and time of a computer that is joined to an Active Directory domain.

Scripting Steps

Listing 58 compares system time (compensated for time zone) on multiple computers, the names or IP addresses of which are retrieved from an array. If the time on any computer does not agree with the standard time, the script resets it.

  1. Create a variable to specify the name of the reference computer.

  2. Create an array to contain the names or IP addresses of the target computers.

  3. On the reference computer, use a GetObject call to connect to the WMI namespace root\cimv2, and set the impersonation level to “impersonate.”

  4. Loop through the array of target computers, performing the following tasks on each.

  5. Use the Exec method of the WshShell object to ping the target computer in order to verify connectivity.

  6. On each computer, use the ExecQuery method to query the Win32_OperatingSystem class.

    This returns two collections of operating system objects, with one object in each collection.

  7. After each of the ExecQuery calls returns, call the VBScript Now function and assign the seconds from each time to a variable.

    The Now function returns the system date and time at the moment it is run.

  8. Assign the difference between the two time variables to another variable, which represents the difference between the times the two Win32_OperatingSystem queries were executed. The moment at which each query runs determines the time that will be retrieved by the LocalDateTime property on that computer.

  9. If the difference between the two time variables is not 0, assign it to a variable. This variable represents the difference between the times the two queries of Win32_OperatingSystem finished executing.

    The time retrieved by the LocalDateTime property on each computer depends on the exact moment when the query executes.

  10. Loop through each operating system object in the collection on the first computer with For Each.

  11. Within the first For Each loop, loop through each operating system object in the collection on the second computer with a nested For Each loop.

  12. Use the LocalDateTime property to retrieve the local system time from the two computers.

  13. Assign the LocalDateTime property from the first (reference) computer to a variable that will be used to set the time on the second (target) computer if necessary.

  14. Truncate the datetime objects returned by LocalDateTime to the date, hour and minute values.

  15. If there is any differential between the two Now values, use it to adjust the reference time before comparing the two times.

  16. Compare the two adjusted dates and times.

  17. If the dates and times are equal, display a message.

  18. If the dates and times are not equal, call the SetDateTime method of Win32_OperatingSystem on the target computer.

  19. Check the return value of the method and display a success or error message.

Listing 58   Time-sync-multi.vbs

  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

On Error Resume Next
 
strReference = "."
arrTargets = Array("client1", "client2", "192.168.0.1", "192.168.0.2")
 
Set objWMIService1 = GetObject("winmgmts:" _
 & "{impersonationLevel=impersonate}!\\" & strReference & "\root\cimv2")
 
For Each strTarget In arrTargets
 
  WScript.Echo VbCrLf & String(80, "-") & VbCrLf & "Target: " & strTarget _
   & VbCrLf
  Set objShell = CreateObject("WScript.Shell")
  Set objExec = objShell.Exec("ping -n 2 -w 1000 " & strTarget)
  strPingResults = LCase(objExec.StdOut.ReadAll)
  If InStr(strPingResults, "reply from") Then
 
    Set objWMIService2 = GetObject("winmgmts:{impersonationLevel=" _
     & "impersonate, (Systemtime)}!\\" & strTarget & "\root\cimv2")
    Set colOSes1 = objWMIService1.ExecQuery("SELECT * FROM " & _
     "Win32_OperatingSystem")
    strTime1 = Now
    Set colOSes2 = objWMIService2.ExecQuery("SELECT * FROM " & _
     "Win32_OperatingSystem")
    strTime2 = Now
    intSeconds1 = CInt(Left(Right(strTime1, 5), 2))
    intSeconds2 = CInt(Left(Right(strTime2, 5), 2))
    intDiff = 0
    If intSeconds1 <> intSeconds2 Then
      intDiff = intSeconds2 - intSeconds1
    End If
 
    For Each objOS1 in colOSes1
      For Each objOS2 in colOSes2
        dtmRefDateTime = objOS1.LocalDateTime
        intDateTime1 = Left(dtmRefDateTime, 14)
        intDateTime2 = Left(objOS2.LocalDateTime, 14)
        If intDiff <> 0 Then
          intDateTime1 = intDateTime1 + intDiff
        End If
        If intDateTime1 = intDateTime2 Then
          Wscript.Echo "Dates and times are equal."
        Else
          intSet = objOS2.SetDateTime(dtmNewDateTime)
          If intSet = 0 Then
            Wscript.Echo "Successfully synchronized date and time on " & _
            strTarget & " with reference (" & strReference & ")."
          Else
            Wscript.Echo "Unable to set new date and time on " & strTarget & _
             "."
          End If
        End If
      Next
    Next
 
  Else
 
    WScript.Echo strTarget & " did not respond to ping."
 
  End If
 
Next

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>time-sync-multi.vbs

--------------------------------------------------------------------------------

Target: client1

Successfully synchronized date and time on client1 with reference (.).

--------------------------------------------------------------------------------

Target: client2

Successfully synchronized date and time on client2 with reference (.).

--------------------------------------------------------------------------------

Target: 192.168.0.1

192.168.0.1 did not respond to ping.

--------------------------------------------------------------------------------

Target: 192.168.0.2

192.168.0.2 did not respond to ping.

Changing Networking Settings in the Registry

You can retrieve and change TCP/IP networking settings by using the registry. The registry contains some networking settings that are not accessible through WMI classes, command-line tools, or the Windows interface.

To work with the registry, use the StdRegProv class of the System Registry WMI provider. This class is located in the \root\default namespace; whereas all the Win32_ classes that were discussed so far in this paper are located in the \root\cimv2 namespace.

caution.gif  Caution
Incorrectly editing the registry may severely damage your system. Before making changes to the registry, you should back up any valued data on the computer.

To use this class, change the lines of the script that connect to WMI to:

Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
 strComputer & "\root\default:StdRegProv")

In the GetObject call that binds (creates a reference) to the WMI service, specify the \root\default namespace as part of the object path (rather than the \root\cimv2 namespace). Then create an instance of the class directly by appending a colon and the name of the StdRegProv class to the end of the object path.

The StdRegProv class returns a reference to a single instance in the form of an SWbemObject, representing the whole registry (of which there is only one per operating system). This is different from the collection of (often) multiple instances in the form of an SWbemObjectSet returned by Win32_NetworkAdapterConfiguration and most other classes used so far. Because this is an SWbemObject rather than an SWbemObjectSet, you do not have to call ExecQuery and work with a collection of instances. Rather, you can use dot notation to call methods of the StdRegProv class directly on the reference, for example:

objReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strEntryName,strValue

If you are unfamiliar with SWbemObject and SwbemObjectSet objects, which are part of the WMI scripting library object model, see these references:

The StdRegProv class does not expose any properties. Table 43 describes the StdRegProv methods.

Table 43   StdRegProv Methods

Method

Description

CheckAccess

Verifies that the user has the specified access permissions.

CreateKey

Creates a subkey.

DeleteKey

Deletes a subkey.

DeleteValue

Deletes a named value.

EnumKey

Enumerates subkeys.

EnumValues

Enumerates the named values of a key.

GetBinaryValue

Gets the binary data value of a named value.

GetDWORDValue

Gets the DWORD data value of a named value.

GetExpandedStringValue

Gets the expanded string data value of a named value.

GetMultiStringValue

Gets the multiple string data values of a named value.

GetStringValue

Gets the string data value of a named value.

SetBinaryValue

Sets the binary data value of a named value.

SetDWORDValue

Sets the DWORD data value of a named value.

SetExpandedStringValue

Sets the expanded string data value of a named value.

SetMultiStringValue

Sets the multiple string values of a named value.

SetStringValue

Sets the string value of a named value.

All the methods in the previous table return a positive integer:

  • 0 indicates successful completion.

  • Numbers greater than 0 indicate that an error occurred.

For more information about the StdRegProv class and its methods, see "StdRegProv" in the WMI SDK at https://go.microsoft.com/fwlink/?LinkId=29999.

The GetStringValue and GetDWORDValue methods return information to the script through an out parameter, a mechanism not previously mentioned in this paper. In the GetStringValue method, the script passes in the first three parameters to tell the method from which entry to fetch the value. The information is returned in the final parameter — in this case in the form of the string variable strValue. After the line executes, this variable now contains the value of the registry entry Hostname in the location HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters. The final line of the script displays this value.

The scripts in this section get and set both string (REG_SZ) and DWORD (REG_DWORD, a 32-bit integer type) values from the registry. Different methods are used to retrieve and set string and DWORD types. The StdRegProv class also includes other methods for multi-string, expanded string, and binary values.

The entry whose value is a string (Hostname) is:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Hostname

The entry whose value is a DWORD (DeadGWDetectDefault) is:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DeadGWDetectDefault

Table 44 describes the registry subkeys that are related to TCP/IP client networking.

Table 44   Registry Subkeys Related to TCP/IP Client Networking

Registry Subkey

Description

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
\Services\Tcpip\Parameters

Contains global TCP/IP configuration settings that apply to all network adapters on the computer.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
\Services\Tcpip\Parameters\Interfaces

Contains TCP/IP configuration settings for each specific adapter (interface) in its subkeys, which are identified by GUID.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
\Services\Dhcp\Parameters\Options

Contains configuration settings for DHCP options in its subkeys.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
\Services\Dnscache\Parameters

Contains configuration settings for local DNS caching resolver service of the DNS client.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
\Services\NetBT\Parameters

Contains global configuration settings for NetBIOS over TCP/IP and WINS that apply to all network adapters on the computer.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
\Services\NetBT\Parameters\Interfaces

Contains configuration settings for NetBIOS over TCP/IP and WINS for each specific adapter (interface) in its subkeys, which are identified by GUID.

For more information about using scripting to configure the registry, including detailed information about many registry entries, see these references:

Getting a String Value from the Registry by Using WMI

This script shows how to retrieve a TCP/IP networking setting (Hostname) from a registry entry whose value is a string (REG_SZ). The script uses the GetStringValue method of the StdRegProv class of the System Registry WMI provider.

Scripting Steps

  1. Create a constant to contain the hexadecimal value for HKEY_LOCAL_MACHINE.

  2. Create a variable and assign the computer name to it. The name can be in the form of either a host name or an IP address.

  3. Create variables for the registry key path and entry name.

  4. Use a GetObject call to connect to the WMI namespace root\default on the specified computer; set the impersonation level to “impersonate"; instantiate the StdRegProv class and assign it to the variable objReg.

  5. Invoke the GetStringValue method of the StdRegProv class, passing it parameters for the subtree, key path and entry name, and assigning the out parameter for the string value to strValue.

  6. Display the entry name and its string value.

Listing 59   Reg-get-string.vbs

  
1
2
3
4
5
6
7
8
9
10

Const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."
strKeyPath = "SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"
strEntryName = "Hostname"
 
Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
 strComputer & "\root\default:StdRegProv")
 
objReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strEntryName,strValue
Wscript.Echo strEntryName & ": " & strValue

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>reg-get-string.vbs

Hostname: client1

Getting a Numeric Value from the Registry by Using WMI

This script shows how to retrieve a TCP/IP networking setting (DeadGWDetectDefault) from a registry entry whose value is a DWORD (REG_DWORD, a 32-bit integer type). The script uses the GetDWORDValue method of the StdRegProv class of the System Registry WMI provider.

Scripting Steps

  1. Create a constant to contain the hexadecimal value for HKEY_LOCAL_MACHINE.

  2. Create a variable and assign the computer name to it. The name can be in the form of either a host name or an IP address.

  3. Create variables for the registry key path and entry name.

  4. Use a GetObject call to connect to the WMI namespace root\default on the specified computer; set the impersonation level to “impersonate"; instantiate the StdRegProv class and assign it to the variable objReg.

  5. Invoke the GetDWORDValue method of the StdRegProv class, passing it parameters for the subtree, key path and entry name, and assigning the outparameter for the DWORD value to dwValue.

  6. Display the entry name and its DWORD value.

Listing 60   Reg-get-dword.vbs

  
1
2
3
4
5
6
7
8
9
10

Const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."
strKeyPath = "SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"
strEntryName = "DeadGWDetectDefault"
 
Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
 strComputer & "\root\default:StdRegProv")
 
objReg.GetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath,strEntryName,dwValue
Wscript.Echo strEntryName & ": " & dwValue

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>reg-get-dword.vbs

DeadGWDetectDefault: 1

Setting a String Value in the Registry by Using WMI

This script shows how to set a TCP/IP networking setting (Hostname) in a registry entry whose value is a string (REG_SZ). The script uses the SetStringValue method of the StdRegProv class of the System Registry WMI provider.

Scripting Steps

  1. Create a constant to contain the hexadecimal value for HKEY_LOCAL_MACHINE.

  2. Create a variable and assign the computer name to it. The name can be in the form of either a host name or an IP address.

  3. Create variables for the registry key path and entry name.

  4. Use a GetObject call to connect to the WMI namespace root\default on the specified computer; set the impersonation level to “impersonate"; instantiate the StdRegProv class and assign it to the variable objReg.

  5. Invoke the SetStringValue method of the StdRegProv class, passing it parameters for the subtree, key path, entry name, and string value.

  6. Invoke the GetStringValue method of the StdRegProv class, passing it parameters for the subtree, key path and entry name, and assigning the outparameter for the string value to strValue.

  7. Display the entry name and its string value.

Listing 61   Reg-set-string.vbs

  
1
2
3
4
5
6
7
8
9
10
11
12
13

Const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."
strKeyPath = "SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"
strEntryName = "Domain"
strValue = "fabrikam.com"
 
Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
 strComputer & "\root\default:StdRegProv")
 
objReg.SetStringValue HKEY_LOCAL_MACHINE, strKeyPath, strEntryName, strValue
 
objReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strEntryName,strValue
Wscript.Echo strEntryName & ": " & strValue

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>reg-set-string.vbs

Domain: fabrikam.com

Setting a Numeric Value in the Registry by Using WMI

This script shows how to set a TCP/IP networking setting (DeadGWDetectDefault) in a registry entry whose value is a DWORD (REG_DWORD, a 32-bit integer type). The script uses the SetDWORDValue method of the StdRegProv class of the System Registry WMI provider.

Scripting Steps

  1. Create a constant to contain the hexadecimal value for HKEY_LOCAL_MACHINE.

  2. Create a variable and assign the computer name to it. The name can be in the form of either a host name or an IP address.

  3. Create variables for the registry key path and entry name.

  4. Use a GetObject call to connect to the WMI namespace root\default on the specified computer; set the impersonation level to “impersonate"; instantiate the StdRegProv class and assign it to the variable objReg.

  5. Invoke the SetDWORDValue method of the StdRegProv class, passing it parameters for the subtree, key path, entry name, and DWORD value.

  6. Invoke the GetDWORDValue method of the StdRegProv class, passing it parameters for the subtree, key path, and entry name, and assigning the outparameter for the DWORD value to dwValue.

  7. Display the entry name and its DWORD value.

Listing 62   Reg-set-dword.vbs

  
1
2
3
4
5
6
7
8
9
10
11
12
13

Const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."
strKeyPath = "SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"
strEntryName = "DeadGWDetectDefault"
dwValue = 1
 
Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
 strComputer & "\root\default:StdRegProv")
 
objReg.SetDWORDValue HKEY_LOCAL_MACHINE, strKeyPath, strEntryName, dwValue
 
objReg.GetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath,strEntryName,dwValue
Wscript.Echo strEntryName & ": " & dwValue

When you use Cscript.exe to run this script, output similar to the following is displayed in the command window:

C:\scripts>reg-set-dword.vbs

DeadGWDetectDefault: 1

Tools for Network Management with Advanced Scripting Techniques

The Windows operating system provides tools and registry keys to use for performing advanced scripting techniques. Table 45 lists the command-line tools to use for managing your network when you use advanced scripting techniques.

Table 45   Tools for Advanced Network Management Techniques

Technology

Tool

Where Available

Command-line tools

Ping.exe

Windows operating systems1

Command-line tools

Remote.exe

Windows Server 2003 Support Tools

Command-line tools

Remote Command Service
(Rcmd.exe and Rcmdsvc.exe)

Windows 2000 Resource Kit

Command-line tools

Remote Console

Windows 2000 Resource Kit

Command-line tools

Rsh.exe and Rshsvc.exe:
TCP/IP Remote Shell Service

Windows 2000 Resource Kit

Command-line tools

Telnet.exe

Windows operating systems

Command-line tools

Timezone.exe:
Daylight Saving Time Update Utility

Windows 2000 Resource Kit

Command-line tools

Tzedit.exe: Time Zone Editor

Windows 2000 Resource Kit (GUI tool)

Command-line tools

Wsremote.exe

Windows XP Support Tools

WSH

WshController

 

WMI

StdRegProv

 

WMI

SwbemDateTime

Windows XP and Windows Server 2003 only

WMI

Win32_ComputerSystem

 

WMI

Win32_CurrentTime

Windows XP and Windows Server 2003 only

WMI

Win32_LocalTime

Windows XP and Windows Server 2003 only

WMI

Win32_NetworkAdapterConfiguration

 

WMI

Win32_NetworkAdapter

 

WMI

Win32_OperatingSystem

 

WMI

Win32_PingStatus

Windows XP and Windows Server 2003 only

WMI

Win32_TimeZone

 

WMI

Win32_UTCTime

Windows XP and Windows Server 2003 only

ADSI

None

 

1 Windows 2000, Windows XP and Windows Server 2003. May also be present on other versions of Windows

Table 46 lists the registry keys for managing your network when you use advanced scripting techniques.

caution.gif  C aution
Incorrectly editing the registry may severely damage your system. Before making changes to the registry, you should back up any valued data on the computer.

Table 46   Registry Subkeys for Managing Networks with Advanced Scripting Techniques

Registry Subkeys

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dhcp\Parameters\Options

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NetBT\Parameters

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NetBT\Parameters\Interfaces