Displaying Version Properties of a Group Policy Object

By Judith Herman, Microsoft Corporation

This article is taken from entries in the Group Policy Team Blog.

On This Page

Displaying Version Properties of a Group Policy Object GPO version number in the GPC GPO version number in the GPT GPMC scripts to display computer and user version numbers

Displaying Version Properties of a Group Policy Object

So you’ve decided you want to write scripts to work with Group Policy. But wait a minute, wasn’t Group Policy designed so you’d never need to write a script? Isn’t that the point after all: Manage your users and computers from a slick MMC console and you’re there?

Well it’s not always that simple. And when you touch Group Policy objects (GPOs) you have to be careful: What if your company Vice President is suddenly prevented from opening a browser or from using Microsoft Word or Microsoft Excel?

Group Policy administrators -- or any administrator that has to touch a GPO -- can quickly become known as the bad guy (or gal) in IT, the one who spits out policies to lock everyone in or everyone out.

One way to avoid being the “bad guy” is to understand certain aspects of Group Policy, including how to write scripts to help solve various problems. In this article we’re going to address the problem of making changes to the user part of Group Policy that refuse to process, and how version numbers for the GPO relate to this issue.

Now, of course being the helpful guy that I am, I want to spare you from any bother, such as unhappy messages from your VP. Really I do. So I started to dig around for a few tricks from inside the Group Policy team, who all live happily in the building next to mine.

I’ll start with the fact that Group Policy has two configurations, computer and user.

If the version numbers for the computer portion of a GPO that are stored in the Sysvol don’t match the Active Directory, the GPO might not process as expected. An example of this unexpected behavior might be that you have made a change to a GPO that doesn’t seem to be applying; the GPO is not replicating.

If you've ever poked around to look at the raw GPO version number, you've probably wondered why the number is so huge and how it gets displayed as a much smaller value when you view the version number using Group Policy Management Console (GPMC).

Let's look at the simplest example, which is the version number for the Local Group Policy Object (LGPO). The LGPO is stored on each computer running Windows 2000 or later in the %windir%\system32\grouppolicy directory. For most computers, this will evaluate to c:\windows\system32\grouppolicy. For our examples, we'll stick with this directory to make things easier. One thing you'll notice is that when you get a directory listing for c:\windows\system32 you will not see the grouppolicy directory. That's because it is a hidden directory. If you navigate directly to the directory (from the command prompt, type the command: cd c:\windows\system32\grouppolicy), you'll see that there is a gpt.ini file, which contains the version number for the GPO. In my particular case, my LGPO contains a gpt.ini file with a version number shown as:

Version=1376303

Hold on. That is impossibly high! This seems to be a fairly large number even for someone who tests out custom ADMX files with their LGPO. However, it starts to make more sense when you look at what's really going on.

The top 16 bits of the version number correspond to the user configuration version. The lower 16 bits of the version number correspond to the computer configuration version. When looking at the version entry in the gpt.ini file what you are seeing is:

Version = [user version number top 16 bits] [computer version number lower 16 bits]

In the case of my LGPO version number 1376303, how do we see what the actual version number is for the user and computer configuration?

Below is a simple way to split the version number into the user and computer version numbers.

  1. First, recognize that the version number is in decimal. Before we can split the number into the two version numbers, we first must convert the decimal value to hexadecimal. The easiest way to perform this conversion is to use the Calculator in Microsoft Windows in scientific mode. Enter the decimal value and then click the Hex button to convert the number. You should see a value of 15002F.

  2. If you are using Calculator, it will not display the leading zeros of the number. In hexadecimal, four hexadecimal characters are equal to 16 bits. When you split the number into two parts you'll need to add two leading zeros to show the full version number in hexadecimal. For our case, I would write this number out as 0015002F. (When written on paper, a 0x is added to the beginning of the number to clarify the number is hexadecimal, 0x0015002F.)

  3. Input the lower 4 hex characters (002F) into the calculator while in hex mode. Then convert this value to decimal by clicking the Dec button. You should see a computer version number of 47 decimal.

  4. Input the upper 4 hex characters (0015) into Calculator while in hex mode. Then convert this value to decimal by clicking the Dec button. You should see a user version number of 21 decimal.

The raw version number of 1376303 split into the computer version of 47 and the user version of 21 now seems much more reasonable. You can use this procedure to look at the number of changes to the computer and user configuration portions of a GPO.

Now that you understand how to split these up manually, here are two scripts that let you do the same thing:

Display the Local GPO Machine Version Number

Display the Local GPO User Version Number

Now if you want to resolve replication issues for domain-based policy, you could use GPMC to automatically look at the report for a GPO. But I’d like to know what’s going on under the hood.

Let's look at the version number associated with a domain-based GPO.

This is where the real danger can occur. Domain-based GPOs can affect, well, the entire domain – including the VP’s domain.

Essentially, the raw version number for a domain-based GPO works exactly the same as it does for a local GPO. 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 above.

Even though the evaluation of the version number works the same way for local and domain-based GPOs, where the version number is located and how we can get to this number are very different. 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 a short sample VBScript script 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 purposes of this discussion. 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 Active Directory objects for learning purposes, try this out on a test domain (that cannot harm VPs in any way).

I open the Ldp tool, connect, and bind it to my test domain. From the view menu, I select tree. From the root of the domain, I navigate through the system container to expand the policies container, where 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 described earlier, 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 picture above, 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 picture below. 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.

GPMC scripts to display computer and user version numbers

The GPMC provides a comprehensive set of COM interfaces that you can use to script many of the operations supported by the console. Check out this download for a set of sample scripts that make use of these interfaces.

These sample scripts can be used with the Windows Server 2008, Windows Vista and earlier versions of GPMC.

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."

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 that if there is a GPO found through the SearchGPOS call, there will be only 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 here:

' ==========================================================================
' 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.