Peter Hinchley

Delayed Enforcement of Active Directory Group Policy Using WMI Filter

Tagged: windows, vbscript, grouppolicy, wmi

I recently had the need to delay the enforcement of a group policy object until 24 hours after a computer had been deployed with Windows Vista. In this article I will explain how I addressed this requirement through the use of a WMI group policy filter.

A WMI group policy filter can be used to restrict the enforcement of a policy to a subset of users or computers. Only those users or computers satisfying the filter will receive the policy object.

Group policy filters are written using WQL, which is a kind of crippled SQL syntax. There are several restrictions that apply when using WQL. Firstly, a WQL query can only target a single table. Therefore, in the context of WMI, you can only query a single namespace. The following is not permitted:

SELECT * FROM Win32_OperatingSystem, Win32_Environment
WHERE LocalDateTime > PolicyTime

Where LocalDateTime is a property of Win32_OperatingSystem and PolicyTime is a custom-defined environment variable accessed via Win32_Environment.

Secondly, you cannot perform any kind of arithmetic in the query. For example, the following is not permitted:

SELECT * From Win32_OperatingSystem
WHERE (LocalDateTime - InstallDate) > 1000000

Where both LocalDateTime and InstallDate are properties of Win32_OperatingSystem.

These limitations make it difficult to build a group policy WMI filter that can be used to exclude computers that were deployed in the past 24 hours.

I resolved this issue by storing the date after which the group policy object is to apply in the Description property of the Win32_OperatingSystem namespace. I chose this property for two reasons. Firstly, the attribute is writeable, and is not assigned a default value. Secondly, the Win32_OperatingSystem namespace includes a property called LocalDateTime that can be used to query the current system time. This configuration permits the use of the following WMI filter:

SELECT LocalDateTime, Description
FROM Win32_OperatingSystem
WHERE LocalDateTime > Description
OR Description = ''

Where Description is specifically set during the operating system deployment process to the UTC time after which the group policy object should be applied. The "OR Description = ''" component of the query ensures the filter applies in the event that the Description property is not set. This was important in our environment, as the policy had to apply to computers that were built without a value assigned to Description.

Now that the query is established, the next step is to show how the Description property is correctly set during the build process (computers in the environment are built using Microsoft SCCM 2007). This is achieved by running the following script at the completion of the build:

Const CONVERT_TO_LOCAL_TIME = True

Set dtmPolicyDate = CreateObject("WbemScripting.SWbemDateTime")
Set oWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set oWin32OS = oWMIService.Get("Win32_OperatingSystem").SpawnInstance_

Set cItems = oWMIService.ExecQuery("Select * From Win32_OperatingSystem")

For Each oItem In cItems
  dtmInstallDate = DatetimeToDate(oItem.InstallDate)
  dtmTempDate = DateAdd("h", 24, dtmInstallDate)
  dtmPolicyDate.SetVarDate dtmTempDate, CONVERT_TO_LOCAL_TIME
  Set oProperty = oWin32OS.SpawnInstance_
  oProperty.Description = dtmPolicyDate
  oProperty.Put_
  WScript.Echo oItem.Description
Next

Function DatetimeToDate(strDate)
 DatetimeToDate = _
   CDate(Mid(strDate, 5, 2) & _
   "/" & _
   Mid(strDate, 7, 2) & _
   "/" & _
   Left(strDate, 4) & _
   " " & _
   Mid (strDate, 9, 2) & _
   ":" & _
   Mid(strDate, 11, 2) & _
   ":" & _
   Mid(strDate, 13, 2))
End Function

The script queries the Win32_OperatingSystem namespace to retrieve the InstallDate property (which stores the time at which the operating system was deployed in UTC format). This value is then converted to VT_DATE format using the DatetimeToDate function. The time is then incremented through DateAdd by 24 hours. The incremented time is then converted back to UTC format through the SetVarDate method of the WbemScripting.SWbemDateTime object. Finally, this value is written into the Description property.

You can confirm the Description field has been set correctly by looking at the Computer Name tab of the System Properties dialog as shown below:

As you can tell, the time is recorded in UTC format, which lists the year, month, day, hour, minutes, and seconds, then a period, 6 zeros, and then a timezone differential (in this case, +600, which equates to 600 minutes, or 10 hours ahead of GMT):

20090909115853.000000+600

By changing the DateAdd line in the script above, it is possible to change the size of the delay between building a computer and enforcing specific group policy settings. In our environment, we used this technique to delay the enforcement of power management settings to 1 day after the completion of the build process. This ensures computers will not go to sleep until at least 24 hours after the build completes.

Your Say