Understanding the domain-based GPO version number (GPMC script included)

In a previous blog post I looked at understanding the raw GPO version number. The example I gave in that article was the version number associated with a local Group Policy object (GPO). Now, let's look at the version number associated with a domain-based GPO.

Essentially, the raw version number for a domain-based GPO works exactly the same as what was described in the earlier article. The version number is divided into a version number for the user portion of the GPO (upper word) and the computer portion of the GPO (lower word). You can use the procedure for splitting the version number into its two parts in exactly the same way as the calculator procedure I gave in the above mentioned blog post.

Okay, so you're probably wondering why I'm bringing this up as a separate topic if the version number works the same way.

Even though the evaluation of the version number works the same way, where the version number and how we can get to this number is way different. In this article, I'm going to show you the two places the version number for a domain-based GPO is stored, show you some tools you can use to view the version numbers and then give you two short sample VB scripts you can use to programmatically view the version numbers.

Unlike the local GPO, a domain-based GPO is stored in two locations; the Group Policy container (GPC) stored in the Active Directory and the Group Policy template (GPT) stored in the sysvol portion of the domain controllers' file system. Both of these components keep different pieces of information about the GPO and so each must store the version number in order to determine that they are in sync.

GPO version number in the GPC:

I have used one of two tools to look at the raw GPO version number in the GPC; Adsiedit and Ldp. Both are GUI tools that allow you to look at Active Directory objects. I'm going to give an example using Ldp.exe simply because I can display all the relevant information in a single frame for the discussion purposes here. Before going on, I would like to say a word of caution here. Making changes using low level Active Directory editing tools could cause problems with the functionality of your domain. If you want to look at AD objects for learning purposes, I would recommend trying this on a test domain.

I have opened the Ldp tool, connected and did a bind to my test domain. From the view menu, I selected tree. From the root of the domain, I navigated through the system container to expand the policies container, where all the GPC portion of my GPOs is stored. In the below picture, I have highlighted a sample GPO I called test1 which is identified by a unique GUID and has a version number of 262146. Using the procedure from the previous blog entry on the GPO version number, (https://blogs.technet.com/grouppolicy/archive/2007/12/14/understanding-the-gpo-version-number.aspx), I figured out this version number is equal to a computer version of 2 and a user version of 4.

GPO version number in the GPT:

The GPT is stored in the sysvol portion of the domain controllers' file system; for example, for my test domain called corp.fourthcoffee.com the GPT is stored at \\corp.fourthcoffee.com\sysvol\corp.fourthcoffee.com\Policies. Each GPO is stored under this folder using the GUID. As you can see from the above picture, the GPC also defines an attribute, gPCFileSysPath, which contains the sysvol path to the GPO's GPT. In my example, the full path to my test1 GPO is \\corp.fourthcoffee.com\sysvol\corp.fourthcoffee.com\Policies\{06C1CDF4-7288-4A6D-B887-8727C2823857}. And I can then type the contents of the GPT.INI file stored directly under that folder to see the version number, as shown in the below picture. Notice this version number (262146) matches the number we saw for the GPC in the Active Directory. That is what we would expect.

In this case, as with the GPC, in order to view the actual values for the computer and user portions of the GPO we need to manually break the value into its lower and upper words. In the next section, I'll show an easier way to find the version numbers for the computer and user portions of the GPO.

Viewing computer and user version numbers using GPMC:

The Group Policy Management Console does all the manual work for you to split apart the raw version number into the computer version number and user version number for both the AD portion, what we call the GPC, and sysvol portion, what we call the GPT, of the GPO. You can view the computer and user version number in the details tab for a specific GPO. Here, I've shown the details tab for the test1 GPO I've been using for my example. This is of course the much easier way to view version numbers.

So, now we have a much better feel for how much work GPMC is saving us. And because GPMC was written to have interfaces that can be called in a script, we can now look at a programmatic way to display the computer and user version numbers from the AD and sysvol.

GPMC scripts to display computer and user version numbers

The Group Policy Management Console (GPMC) provides a comprehensive set of COM interfaces that you can use to script many of the operations supported by the console. This download contains a set of sample scripts that make use of these interfaces.

https://www.microsoft.com/downloads/details.aspx?FamilyId=38C1A89B-A6D2-4F2A-A944-9236999AEE65&displaylang=en

These sample scripts can be used with the Windows Server 2008, Vista and earlier versions of GPMC. This sample script is provided, as is. Remember to test the scripts before applying the scripts to your production environment.

For the purposes of this discussion, I'm going to create a simpler example to just look at the computer and user version numbers for our example GPO called, "test1" in my test domain called, "corp.fourthcoffee.com." Note: this script is provided strictly as is.

The sample script starts by instantiating the GPM and GPMConstants objects.

set oGPM = CreateObject("GPMGMT.GPM")

set oGPConst = oGPM.GetConstants()

Then the script instantiates an oGPSearch object that defines the search criteria. For the specified domain name and domain controller, the script defines a search criteria for the specific Group Policy object name of "test1."

set oGPSearch = oGPM.CreateSearchCriteria()

set oDom = oGPM.GetDomain( strDomainName, strDC, USE_THIS_DC)

oGPSearch.Add oGPConst.SearchPropertyGPODisplayName, _

                      oGPConst.SearchOpEquals, strPolicyName

set oGPSearchResults = oDom.SearchGPOs(oGPsearch)

Since all display names are assumed to be unique we know if there is a GPO found through the SearchGPOS call, there will only be one GPO returned.

set oGPO = oGPSearchResults.Item(1)  

The script displays the DS version number properties (UserDSVersionNumber and ComputerDSVersionNumber ) and the sysvol version number properties (UserSysvolVersionNumber and ComputerSysvolVersionNumber).

WScript.Echo "The user version number from the Active Directory = " & _

                    oGPO.UserDSVersionNumber

WScript.Echo "The computer version number from the Active Directory = " & _

                     oGPO.ComputerDSVersionNumber

Wscript.Echo "The user version number from the sysvol = " & _

                      oGPO.UserSysvolVersionNumber

WScript.Echo "The computer version number from the sysvol = " & _

                       oGPO.ComputerSysvolVersionNumber

The full script is listed below.

' ==========================================================================

' VBScript Source File

' NAME: DomainGPOPolicyVersion.vbs

' AUTHOR: System Administrator , Fourth Coffee Company

' DATE : 1/08/2007

' COMMENT: Displays the computer and user Version numbers for a

'     domain-based GPO as stored in the GPC (AD) and GPT (sysvol)

' ==========================================================================

Const USE_THIS_DC =0

strPolicyName = "test1"

strDC = "fourthcoffee"

strDomainName = "corp.fourthcoffee.com"

 

' Create objects for searching domain

set oGPM = CreateObject("GPMGMT.GPM")

set oGPConst = oGPM.GetConstants()

set oGPSearch = oGPM.CreateSearchCriteria()

set oDom = oGPM.GetDomain( strDomainName, strDC, USE_THIS_DC)

oGPSearch.Add oGPConst.SearchPropertyGPODisplayName, _

                         oGPConst.SearchOpEquals, strPolicyName

set oGPSearchResults = oDom.SearchGPOs(oGPsearch)

 

' Verify we have found a GPO. If not quit.

If oGPSearchResults.Count <= 0 Then

WScript.Echo "The Group Policy object " & strPolicyName & " was not found!"_

&vbCrLf & "on Domain Controller " & strDC

WScript.Quit()

End If

 

' If found policy then print out version numbers

set oGPO = oGPSearchResults.Item(1)

WScript.Echo "The user version number from the Active Directory = " & _

                    oGPO.UserDSVersionNumber

WScript.Echo "The computer version number from the Active Directory = " & _

                     oGPO.ComputerDSVersionNumber

Wscript.Echo "The user version number from the sysvol = " & _

                      oGPO.UserSysvolVersionNumber

WScript.Echo "The computer version number from the sysvol = " & _

                       oGPO.ComputerSysvolVersionNumber

' ==========================================================================

Running the script will display all the version numbers as the below picture shows.

Now, you have an introduction to the GPO version number and how it relates to the GPO structure. And you have a new sample gpmc script that can be modified to programmatically display other properties of a GPO.

Judith Herman, Group Policy Programming Writer