List empty GPOs, advanced mode

(Automate trad)
In a previous post,we saw how list empty GPOs using GroupPolicy GPOReport module and then we briefly mentioned a second method to do so. We will now focus on this second method

Why try another method ?

The generation of a GPO report uses a lot of system resources and takes a considerable time in its use is not really an option if we list a number GPO , knowing that usually the corollary to ” many GPO ” is “A lot of shared resources .”

Inspect the object ActiveDirectory

The AD object storing a GPO groupPolicyContainer is the type we will look at its various members.

PS>get-adobject (Get-ADObject -Filter 'ObjectClass -eq "groupPolicyContainer"' -SearchBase 'CN=Policies,CN=System,DC=fabrikam,dc=com')[0].distinguishedName -properties * | get-member -membertype property

Here come the list :

  • CanonicalName
  • CN
  • Created
  • createTimeStamp
  • Deleted
  • Description
  • DisplayName
  • DistinguishedName
  • dSCorePropagationData
  • flags
  • gPCFileSysPath
  • gPCFunctionalityVersion
  • gPCMachineExtensionNames
  • gPCUserExtensionNames
  • instanceType
  • isCriticalSystemObject
  • isDeleted
  • LastKnownParent
  • Modified
  • modifyTimeStamp
  • Name
  • nTSecurityDescriptor
  • ObjectCategory
  • ObjectClass
  • ObjectGUID
  • ProtectedFromAccidentalDeletion
  • sDRightsEffective
  • showInAdvancedViewOnly
  • systemFlags
  • uSNChanged
  • uSNCreated
  • versionNumber
  • whenChanged
  • whenCreated

The members flag and gPCFileSysPath may interest us. Flag allows us to know if one or more of the GPO were disabled _ we do not have to use it in our _ and gPCFileSysPath case contains the data access of the GPO on the sysvol path .

GPO Storage

Look what’s in the directory stored by gPCFileSysPath :

PS> gci $gpo.gPCFileSysPath


    Directory: \\fabrikam.com\sysvol\fabrikam.com\Policies\{12345678-9ABC-EF01-234-56789ABCDEF0}


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        06/06/2011     11:54            Adm
d----        06/06/2011     12:39            MACHINE
d----        06/06/2011     12:39            USER
-a---        04/04/2013     13:31         28 gpt.ini

Both directories contain MACHINE and USER respectively Computer and User GPO settings and as we suspect GPO is empty when both directories are empty

To check the contents of a directory, we Castthe result of Get-CHildItem as a boolean or we use Test-Path.To determine the fastest method we will make a series of measures on cmdlets with full and empty GPO GPO.

PS> measure-command {test-path "$($gpo.gPCFileSysPath)\User\*"}


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 65
Ticks             : 655303
TotalDays         : 7,58452546296296E-07
TotalHours        : 1,82028611111111E-05
TotalMinutes      : 0,00109217166666667
TotalSeconds      : 0,0655303
TotalMilliseconds : 65,5303

PS> measure-command {[bool](gci "$($gpo.gPCFileSysPath)\User") }


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 44
Ticks             : 443332
TotalDays         : 5,13115740740741E-07
TotalHours        : 1,23147777777778E-05
TotalMinutes      : 0,000738886666666667
TotalSeconds      : 0,0443332
TotalMilliseconds : 44,3332


PS> measure-Command {test-path "$($gpo.gPCFileSysPath)\User"}


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 21
Ticks             : 210956
TotalDays         : 2,44162037037037E-07
TotalHours        : 5,85988888888889E-06
TotalMinutes      : 0,000351593333333333
TotalSeconds      : 0,0210956
TotalMilliseconds : 21,0956


PS> measure-Command {[bool](gci "$($gpo.gPCFileSysPath)\User") }


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 35
Ticks             : 356400
TotalDays         : 4,125E-07
TotalHours        : 9,9E-06
TotalMinutes      : 0,000594
TotalSeconds      : 0,03564
TotalMilliseconds : 35,64

In this sequence , the use of gci is faster for full gpo while test -path is faster empty gpo … Optimists , we consider that we shall meet GPO full as empty , so we use gci .

We can determine that a GPO is empty if the two component User and Machine are empty , so we use the following condition:

where-object { [bool]( gci "$($_.gPCFileSysPath)\User") -eq $false -and [bool](gci "$($_.gPCFileSysPath)\Machine") -eq $false } 

put it all together

Here is the proposed ” oneliner ”

Get-ADObject -Filter 'ObjectClass -eq "groupPolicyContainer"' -SearchBase 'CN=Policies,CN=System,DC=fabrikam,DC=com' |% { Get-Adobject $_.distinguishedName -properties * } |?{ [bool]( gci "$($_.gPCFileSysPath)\User") -eq $false -and [bool](gci "$($_.gPCFileSysPath)\Machine") -eq $false } | select DisplayName

Leave a Reply

Your email address will not be published. Required fields are marked *