Script to Generate a Group Policy Object (GPO) Version Report

by Jeremy Saunders on May 23, 2014

Is there a version match between your Group Policy Object (GPO) containers and templates?

This PowerShell script will check that the version of each GPO is consistent in the Active Directory Group Policy Container (GPC) and on each Domain Controller in the Group Policy Template (GPT).

All Windows Operating Systems (since Windows 2000) will apply the GPO regardless of a version mismatch. However, a version mismatch will typically mean that some settings will simply not be applied because they haven’t been replicated correctly across the environment. Replication issues with good old flaky FRS and perhaps (but rarely) the newer DFS-R is often the reason that the GPT gets out of sync and lags behind the GPC. This is such a common problem.

However, I’ve taken this one step further by verifying the GPT on every Domain Controller. The output from this script often provides an “aha moment”, as it will paint the picture for why some group policy settings are inconsistently applied across your environment, and even within the same Active Directory site!

Microsoft added the Infrastructure Status feature to the GPMC in Windows 8/2012 that more or less provides this capability on a per-domain or per-GPO basis. However, it’s very slow and cumbersome to run in a large environment and is limited to the GUI, with no ability to run it from the command line or via PowerShell. Furthermore, it’s feedback to the Sys Admin or IT Pro is very poor whilst processing. In a large environment I have left it sitting in the “Generating report…” state overnight and ended up just closing the GPMC the next day and giving up.

This is a function you were previously able to do using the GPOTOOL command line tool, which does not work on the newer Operating Systems. In fact the last official release of the tool was as part of the Windows 2003 R2 resource kit. Whilst you can search and find a version that has been reported to work with at least Windows 2008 R2, it’s unsupported, so consistency of results are not guaranteed.

Darren Mar-Elia (GPO Guy) of SDM Software has a PowerShell module that will also achieve this. Thanks to Darren for his advice and support.

The following screen shots are made up of the output of one GPO across 14 Domain Controllers from a recent health check I completed.

  • You can see the overall GPC version and then the individual User and Machine GPC versions. Compare this to the GPT versions for each Domain Controller.
  • You will also see the size of the GPT folder on each Domain Controller, and the number of files and folders within. Compare this across all Domain Controllers.

Compare-GPO-Versions-Output-1of2 Compare-GPO-Versions-Output-2of2

The following screen shot shows the output from the CSV file that can be used in a report. Here I’ve included two GPOs that stand out. Note the inconsistencies across the Domain Controllers for the GPT versions, GPT folder size and file count.

Compare-GPO-Versions-CSV

I will be adding some new features to this script as soon as I have time, but wanted to publish it as is and get some feedback. The work to be completed is:

  • Modularize to remove some duplicate code.
  • Add file checksums for GPT content using a hash algorithm.
  • Get the output into a hash table.
  • Add more command line parameters.
  • Change the presentation of the script output so that it’s easier to read for those that are colour blind.

Here is the Get-GPOVersionReport.ps1 (1128 downloads)  script:

<#
  Is there a version match between your Group Policy Object (GPO) containers and templates?
  This script will check that the version of each GPO is consistent in the Active Directory
  Group Policy Container (GPC) and on each Domain Controller in the Group Policy Template
  (GPT).

  All Windows Operating Systems since Windows 2000 will apply the GPO regardless of a
  version mismatch. However, a version mismatch will typically mean that some settings will
  not be applied. Replication issues with good old flaky FRS and perhaps (but rarely) the
  newer DFS-R is often the reason that the GPT gets out of sync and lags behind the GPC.

  However, I've taken this one step further by verifying the GPT on every Domain Controller.
  The output from this script often provides an aha moment, as it will paint the picture for
  why some group policy settings are inconsistently applied across your environment, and
  even within the same site!

  The following article provides an excellent explanation of how the group policy version
  number works:
  - http://technet.microsoft.com/en-us/library/ff730972.aspx

  Syntax examples:

  - To execute the script in the current Domain:
      Get-GPOVersionReport.ps1

  - To execute the script in a trusted Domain:
      Get-GPOVersionReport.ps1 -TrustedDomain mydemosthatrock.com

  Script Name: Get-GPOVersionReport.ps1
  Release: 1.4
  Written by Jeremy@jhouseconsulting.com 23rd April 2014
  Modified by Jeremy@jhouseconsulting.com 7th June 2016

  To be completed:
  - Add an IsLinked column
  - Modularize to remove some duplicate code.
  - Add file checksums for GPT content using a hash algorithm.
  - Get the output into a hash table.
  - Add more command line parameters.
  - Change the presentation of the script output so that it's easier to read for those that
    are color blind.

#>
#-------------------------------------------------------------
param([String]$TrustedDomain)
#-------------------------------------------------------------

# Set this to true to count the files and folders in each GPT
$CountFilesandFolders = $True

# Set this to true to check the SYSVOL on individual Domain
# Controllers. If set to false, it will just check the domain
# SYSVOL.
$CheckIndividualDCs = $True

# Set this value to true if you want verbose output to the console
$VerboseConsoleOutput = $True

#-------------------------------------------------------------
# Get the script path
$ScriptPath = {Split-Path $MyInvocation.ScriptName}
$ScriptName = [System.IO.Path]::GetFilenameWithoutExtension($MyInvocation.MyCommand.Path.ToString())
$ReferenceFile = $(&$ScriptPath) + "\" + $ScriptName + ".csv"

if ([String]::IsNullOrEmpty($TrustedDomain)) {
  # Get the Current Domain Information
  $domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
} else {
  $context = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext("domain",$TrustedDomain)
  Try {
    $domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($context)
  }
  Catch [exception] {
    write-host -ForegroundColor red $_.Exception.Message
    Exit
  }
}

# Get AD Domain Name
$DomainDNS = $Domain.Name
# Get AD Distinguished Name
$DomainDistinguishedName = $Domain.GetDirectoryEntry() | select -ExpandProperty DistinguishedName  

Write-Host -ForegroundColor green "Domain: $domain`n"

$GPOPoliciesDN = "CN=Policies,CN=System,$DomainDistinguishedName"

Write-Host -ForegroundColor Green "Reading GPO information from Active Directory ($GPOPoliciesDN)..."
$GPOPoliciesADSI = [ADSI]"LDAP://$GPOPoliciesDN"
[array]$GPOPolicies = $GPOPoliciesADSI.psbase.children
$DomainGPOList = @()
ForEach ($GPO in $GPOPolicies) { [array]$DomainGPOList += $GPO.Name }
$DomainGPOList = $DomainGPOList | sort-object 
[int]$DomainGPOListCount = ($DomainGPOList | Measure-Object).Count
If ($DomainGPOListCount -eq 0) {
  Write-Host -ForegroundColor red "No GPOs found in Active Directory!"
  Exit
}
Write-Host -ForegroundColor Green "- Discovered $DomainGPOListCount GPCs (Group Policy Containers) in Active Directory ($GPOPoliciesDN)`n"

If ($CheckIndividualDCs) {
  # Get the names of all the Domain Contollers in $domain
  Write-Host -ForegroundColor green "Getting all Domain Controllers from $domain ..."
  $DomainControllers = $domain | ForEach-Object -Process { $_.DomainControllers } | Select-Object -Property Name
  [int]$DomainControllerCount = ($DomainControllers | Measure-Object).Count
  If ($DomainControllerCount -ne 0) {
    Write-Host -ForegroundColor green "- Found $DomainControllerCount Domain Controllers."
  }
}

$array = @()
$TotalGPCsProcessed = 0

ForEach ($GPC in $DomainGPOList) {
  $GPCADSI = [ADSI]"LDAP://CN=$GPC,$GPOPoliciesDN"
  $name = $GPCADSI.properties.name[0]
  $displayname = $GPCADSI.properties.displayname[0]
  $gPCFileSysPath = $GPCADSI.properties.gPCFileSysPath[0]
  $percent = "{0:P}" -f ($TotalGPCsProcessed/$DomainGPOListCount)
  write-host -ForegroundColor red -backgroundcolor yellow "`n---------- Processing $($TotalGPCsProcessed + 1) of $DomainGPOListCount GPOs = $percent complete ----------"
  write-host -ForegroundColor green "DisplayName: $displayname"
  write-host -ForegroundColor green "- Name: $name"
  write-host -ForegroundColor green "- FilePath: $gPCFileSysPath"
  $gpcVersion = $GPCADSI.properties.versionnumber[0]
  [INT]$UserGPCVersion = "{0:d}" -f [INT]("0x" + [String]::Format("{0:x8}", $gpcVersion).Substring(0,[String]::Format("{0:x8}", $gpcVersion).Length/2))
  [INT]$MachineGPCVersion = "{0:d}" -f [INT]("0x" + [String]::Format("{0:x8}", $gpcVersion).Substring(4,[String]::Format("{0:x8}", $gpcVersion).Length/2))
  write-host -ForegroundColor green "- GPC Version: $gpcVersion"
  write-host -ForegroundColor green "- User GPC Version: $UserGPCVersion"
  write-host -ForegroundColor green "- Machine GPC Version: $MachineGPCVersion"

  $gptVersion = ""
  $UserGPTVersion = ""
  $MachineGPTVersion = ""
  $GPTStatus = ""
  $SizeinBytes = ""
  $FileCount = ""
  $FolderCount = ""

  If ($CheckIndividualDCs) {

    If ($DomainControllerCount -ne 0) {

      $DCsProcessed = 0

      # Review the GPT.ini from each Domain Controller
      Write-Host -ForegroundColor green "`nProcessing each Domain controller..."
      ForEach ($dc in $DomainControllers) {

        $DCName = $($dc.Name)
        $DCsProcessed ++

        write-host -ForegroundColor green "`n$($DCName):"

        # Note that I have changed the Test-Connection count to 3 to cater for a response
        # over slow WAN links and cloud services, otherwise some DCs may fail the "Test"
        # and register as unreachable.
        If (Test-Connection -Cn $DCName -BufferSize 16 -Count 3 -ea 0 -quiet) {

          # GPT.ini path for the current Domain Controller
          [array]$GPTPath = $GPCADSI.properties.gPCFileSysPath -Split [regex]::Escape('\')
          [string]$GPTPath = "\\$DCName\" + ($GPTPath[3..6] -join "\")
          [string]$GPTiniPath = "$GPTPath\gpt.ini"

          # Testing the $GPTPath
          If (Test-Path -Path $GPTPath) {

            # Testing the $GPTiniPath
            If (Test-Path -Path $GPTiniPath) {

              $DCStatus = "Online"

              # Get GPT Version from the gpt.ini file and convert it from a string to an integer.
              If ($VerboseConsoleOutput) {
                Write-Host -ForegroundColor green "- Retrieving contents of $GPTiniPath"
              }
              $TotalTime = measure-command {[int]$gptVersion = (Get-Content "$GPTiniPath" | Where-Object {$_ -like "Version=*"}).Split("=")[1]}
              $TotalSeconds = $TotalTime.TotalSeconds
              If ($VerboseConsoleOutput) {
                Write-Host -ForegroundColor green "  - completed in $TotalSeconds seconds."
              }

              [INT]$UserGPTVersion = "{0:d}" -f [INT]("0x" + [String]::Format("{0:x8}", $gptVersion).Substring(0,[String]::Format("{0:x8}", $gptVersion).Length/2))
              [INT]$MachineGPTVersion = "{0:d}" -f [INT]("0x" + [String]::Format("{0:x8}", $gptVersion).Substring(4,[String]::Format("{0:x8}", $gptVersion).Length/2))

              If ($gpcVersion -eq $gptVersion) {
                If (!($gpcVersion -eq 0 -AND $gptVersion -eq 0)) {
                  $GPTStatus = "Match"
                  $ForegroundColor = "Green"
                } else {
                  $GPTStatus = "Empty"
                  $ForegroundColor = "Yellow"
                }
              } else {
                $GPTStatus = "Mismatch"
                $ForegroundColor = "Red"
              }
              If ($VerboseConsoleOutput) {
                write-host -ForegroundColor $ForegroundColor "- GPT Version: $gptVersion"
                write-host -ForegroundColor $ForegroundColor "- User GPT Version: $UserGPTVersion"
                write-host -ForegroundColor $ForegroundColor "- Machine GPT Version: $MachineGPTVersion"
                Write-host -ForegroundColor $ForegroundColor "- Status: $GPTStatus"
              }

              If ($CountFilesandFolders) {
                # Calculate the size of the GPT in bytes and megabytes as well as getting the folder and file count.
                If ($VerboseConsoleOutput) {
                  Write-Host -ForegroundColor green "- Retrieving contents of $GPTPath"
                }
                $TotalTime = measure-command {$colItems = Get-ChildItem "$GPTPath" –force -recurse}
                $TotalSeconds = $TotalTime.TotalSeconds
                If ($VerboseConsoleOutput) {
                  Write-Host -ForegroundColor green "  - completed in $TotalSeconds seconds."
                }
                $FolderCount = $colItems | where {$_.PSIsContainer} | Measure-Object | Select-Object -Expand Count
                $FileCount = $colItems | where {!$_.PSIsContainer} | Measure-Object | Select-Object -Expand Count
                $size = ($colItems | Measure-Object -property length -sum)
                $SizeinMB = "{0:N2}" -f ($size.sum / 1MB) + " MB"
                $SizeinBytes = "{0:N0}" -f $size.sum + " bytes"
                If ($VerboseConsoleOutput) {
                  write-host -ForegroundColor green "- Size: $SizeinMB ($SizeinBytes)"
                  write-host -ForegroundColor green "- Contains $FileCount Files, $FolderCount Folders"
                }
              }

            } Else {
              If ($VerboseConsoleOutput) {
                Write-Host -ForegroundColor red "- $DCName is not reachable via the $GPTiniPath path."
              }
              $DCStatus = "GPT.ini not reachable"
            }

          } Else {
            If ($VerboseConsoleOutput) {
              Write-Host -ForegroundColor red "- $DCName is not reachable via the $GPTPath path."
            }
            $DCStatus = "GPT path not reachable"
          }

        } Else {
          If ($VerboseConsoleOutput) {
            Write-Host -ForegroundColor red "- $DCName is not reachable or offline."
          }
          $DCStatus = "Not reachable"
        }

        $obj = New-Object -TypeName PSObject
        $obj | Add-Member -MemberType NoteProperty -Name "Name" -value $name
        $obj | Add-Member -MemberType NoteProperty -Name "DisplayName" -value $displayname
        $obj | Add-Member -MemberType NoteProperty -Name "FilePath" -value $gPCFileSysPath
        $obj | Add-Member -MemberType NoteProperty -Name "GPC Version" -value $gpcVersion
        $obj | Add-Member -MemberType NoteProperty -Name "User GPC Version" -value $UserGPCVersion
        $obj | Add-Member -MemberType NoteProperty -Name "Machine GPC Version" -value $MachineGPCVersion
        $obj | Add-Member -MemberType NoteProperty -Name "DC" -value $DCName
        $obj | Add-Member -MemberType NoteProperty -Name "DC Status" -value $DCStatus
        $obj | Add-Member -MemberType NoteProperty -Name "GPT Version" -value $gptVersion
        $obj | Add-Member -MemberType NoteProperty -Name "User GPT Version" -value $UserGPTVersion
        $obj | Add-Member -MemberType NoteProperty -Name "Machine GPT Version" -value $MachineGPTVersion
        $obj | Add-Member -MemberType NoteProperty -Name "GPT Status" -value $GPTStatus
        If ($CountFilesandFolders) {
          $obj | Add-Member -MemberType NoteProperty -Name "Size (Bytes)" -value $SizeinBytes
          $obj | Add-Member -MemberType NoteProperty -Name "File Count" -value $FileCount
          $obj | Add-Member -MemberType NoteProperty -Name "Folder Count" -value $FolderCount
        }
        $array += $obj

        # Reset variables
        [string]$gptVersion = ""
        [string]$UserGPTVersion = ""
        [string]$MachineGPTVersion = ""
        $GPTStatus = ""
        $SizeinBytes = ""
        $FileCount = ""
        $FolderCount = ""

      }#FOREACH

    } Else {
      Write-Host -ForegroundColor red "No Domain Controllers found!"
      Exit
    }

  } else {

    # GPT.ini path for the current Domain Controller
    [string]$GPTPath = $GPCADSI.properties.gPCFileSysPath
    [string]$GPTiniPath = "$GPTPath\gpt.ini"

    # Testing the $GPTPath
    If (Test-Path -Path $GPTPath) {

      # Testing the $GPTiniPath
      If (Test-Path -Path $GPTiniPath) {

        $GPTiniExists = "Exists"

        # Get GPT Version from the gpt.ini file and convert it from a string to an integer.
        If ($VerboseConsoleOutput) {
          Write-Host -ForegroundColor green "- Retrieving contents of $GPTiniPath"
        }
        $TotalTime = measure-command {[int]$gptVersion = (Get-Content "$GPTiniPath" | Where-Object {$_ -like "Version=*"}).Split("=")[1]}
        $TotalSeconds = $TotalTime.TotalSeconds
        If ($VerboseConsoleOutput) {
          Write-Host -ForegroundColor green "  - completed in $TotalSeconds seconds."
        }

        [INT]$UserGPTVersion = "{0:d}" -f [INT]("0x" + [String]::Format("{0:x8}", $gptVersion).Substring(0,[String]::Format("{0:x8}", $gptVersion).Length/2))
        [INT]$MachineGPTVersion = "{0:d}" -f [INT]("0x" + [String]::Format("{0:x8}", $gptVersion).Substring(4,[String]::Format("{0:x8}", $gptVersion).Length/2))

        If ($gpcVersion -eq $gptVersion) {
          If (!($gpcVersion -eq 0 -AND $gptVersion -eq 0)) {
            $GPTStatus = "Match"
            $ForegroundColor = "Green"
          } else {
            $GPTStatus = "Empty"
            $ForegroundColor = "Yellow"
          }
        } else {
          $GPTStatus = "Mismatch"
          $ForegroundColor = "Red"
        }
        If ($VerboseConsoleOutput) {
          write-host -ForegroundColor $ForegroundColor "- GPT Version: $gptVersion"
          write-host -ForegroundColor $ForegroundColor "- User GPT Version: $UserGPTVersion"
          write-host -ForegroundColor $ForegroundColor "- Machine GPT Version: $MachineGPTVersion"
          Write-host -ForegroundColor $ForegroundColor "- Status: $GPTStatus"
        }

        If ($CountFilesandFolders) {
          # Calculate the size of the GPT in bytes and megabytes as well as getting the folder and file count.
          If ($VerboseConsoleOutput) {
            Write-Host -ForegroundColor green "- Retrieving contents of $GPTPath"
          }
          $TotalTime = measure-command {$colItems = Get-ChildItem "$GPTPath" –force -recurse}
          $TotalSeconds = $TotalTime.TotalSeconds
          If ($VerboseConsoleOutput) {
            Write-Host -ForegroundColor green "  - completed in $TotalSeconds seconds."
          }
          $FolderCount = $colItems | where {$_.PSIsContainer} | Measure-Object | Select-Object -Expand Count
          $FileCount = $colItems | where {!$_.PSIsContainer} | Measure-Object | Select-Object -Expand Count
          $size = ($colItems | Measure-Object -property length -sum)
          $SizeinMB = "{0:N2}" -f ($size.sum / 1MB) + " MB"
          $SizeinBytes = "{0:N0}" -f $size.sum + " bytes"
          If ($VerboseConsoleOutput) {
            write-host -ForegroundColor green "- Size: $SizeinMB ($SizeinBytes)"
            write-host -ForegroundColor green "- Contains $FileCount Files, $FolderCount Folders"
          }
        }
      } Else {
        If ($VerboseConsoleOutput) {
          Write-Host -ForegroundColor red "- $DCName is not reachable via the $GPTiniPath path."
        }
        $GPTiniExists = "GPT.ini not reachable"
      }

    } Else {
      If ($VerboseConsoleOutput) {
        Write-Host -ForegroundColor red "- $DCName is not reachable via the $GPTPath path."
      }
      $GPTiniExists = "GPT path not reachable"
    }

    $obj = New-Object -TypeName PSObject
    $obj | Add-Member -MemberType NoteProperty -Name "Name" -value $name
    $obj | Add-Member -MemberType NoteProperty -Name "DisplayName" -value $displayname
    $obj | Add-Member -MemberType NoteProperty -Name "FilePath" -value $gPCFileSysPath
    $obj | Add-Member -MemberType NoteProperty -Name "GPC Version" -value $gpcVersion
    $obj | Add-Member -MemberType NoteProperty -Name "User GPC Version" -value $UserGPCVersion
    $obj | Add-Member -MemberType NoteProperty -Name "Machine GPC Version" -value $MachineGPCVersion
    $obj | Add-Member -MemberType NoteProperty -Name "GPT ini Exists" -value $GPTiniExists
    $obj | Add-Member -MemberType NoteProperty -Name "GPT Version" -value $gptVersion
    $obj | Add-Member -MemberType NoteProperty -Name "User GPT Version" -value $UserGPTVersion
    $obj | Add-Member -MemberType NoteProperty -Name "Machine GPT Version" -value $MachineGPTVersion
    $obj | Add-Member -MemberType NoteProperty -Name "GPT Status" -value $GPTStatus
    If ($CountFilesandFolders) {
      $obj | Add-Member -MemberType NoteProperty -Name "Size (Bytes)" -value $SizeinBytes
      $obj | Add-Member -MemberType NoteProperty -Name "File Count" -value $FileCount
      $obj | Add-Member -MemberType NoteProperty -Name "Folder Count" -value $FolderCount
    }
    $array += $obj

  }#IF

  $TotalGPCsProcessed ++

}#FOREACH

write-host -ForegroundColor red -backgroundcolor yellow "`n---------- Processed all GPOs = 100% complete ----------"

# Write-Output $array | Format-Table
$array | Export-Csv -Path "$ReferenceFile" -Delimiter ';' -NoTypeInformation

# Remove the quotes
(get-content "$ReferenceFile") |% {$_ -replace '"',""} | out-file "$ReferenceFile" -Fo -En ascii

Enjoy!

Jeremy Saunders

Jeremy Saunders

Independent Consultant | Contractor | Microsoft & Citrix Specialist | Desktop Virtualization Specialist at J House Consulting
Jeremy is a highly respected, IT Professional, with over 30 years’ experience in the industry. He is an independent IT consultant providing expertise to enterprise, corporate, higher education and government clients. His skill set, high ethical standards, integrity, morals and attention to detail, coupled with his friendly nature and exceptional design and problem solving skills, makes him one of the most highly respected and sought after Microsoft and Citrix technical resources in Australia. His alignment with industry and vendor best practices puts him amongst the leaders of his field.
Jeremy Saunders
Jeremy Saunders
Jeremy Saunders
  • Pingback: Active Directory Health Check, Audit and Remediation Scripts()

  • pseudonym

    Hey there. I would love to run this script but am having problems. The easy one was the parser error where I had to change ” to ‘ when you were doing the number formatting. The issue I am having now is that no matter what I do or how many } I add, when I try to run the script I get the following error:

    Missing closing ‘}’ in statement block.

    No idea why this is happening or where the problem in the script might be. Would you be able to give me a hand? I could really use this script for a AD Health Checkup that I am doing.

    • Hi, Sorry for taking a couple of weeks to respond. This is unusual as I and others have been using this script without issue. However, I have just updated this post to the latest version. Perhaps there was an issue with the version I had previously posted, or the upload/download was corrupted. Please try again and let me know if it’s okay for you now. Otherwise send me your exact error. Cheers, Jeremy

      • pseudonym

        Hey there. No worries. It is actually the strangest thing, but I did get it to work. Try as I might if I saved it in Notepad++ I kept getting that error. I looked, my co-workers looked.. no one could figure out what was wrong. Then, I put it into PowerGUI and saved it.. same script, nothing changed. Just a copy and paste from Notepad++. For some reason that worked. I really am at a loss to explain why.

        • Yeah, Notepad++ hides invalid/special characters. I would always first paste into Notepad and then you have clear text. However, you can also right click on the hyperlink and save as, which just saves the uploaded script as a txt file. Then just rename the extension. Glad you got it working.

  • tomwww

    Is there anyway to run this against just one GPO and not every single one? We have a fairly large environment with 160!!!!! gpo’s. We only need to target one or two GPO’s. Thanks!

    • The whole point of this script to do a health check against all GPOs, so why would you only want to select one? That said, there are a number of different ways you can code it in, but I personally don’t have time to do that for you at present. Have a go at modifying the script for yourself. However, 160 GPOs is a small environment from my experience. Just leave the script running for a while and it’ll complete them all.
      Cheers,
      Jeremy

  • Thanks for the feedback Douglas. I have updated the script with your fix.

    Cheers,
    Jeremy

  • Luca Cirillo

    Great script indeed. I will be running your script shortly on a mixed domain with w2k8 and w2k3 DCs. I did a quick check manually on the size of the C:windowssysvoldomainPolicies folder and find that across w2k8 DCs it is the same but there is a difference in the size of this folder when comparing the w2k3 DC to a w2k8 DC. I expected that the sysvol size would be the same across different version of the windows OS across DCs. I must be lacking some knowledge in this regard.

    • You could have morphed folders, old folders from restores, etc, on the 2003 DCs that were old and there before you had the 2008 DCs in place. This script will get the GPC’s from AD and make sure there is a matching GPT on every DC in that Domain. The output shows the folder size, number f files, etc, so you’ll see if there is anything missing here. This is the whole point of the script so that you know that the Group Policies will apply as expected no matter which DC the client is connected to.

Previous post:

Next post: