One-Liner: Use PowerShell to Get GPOs Containing User Settings

Last week we used Get-ADObject to find GPOs based on their flags attribute. We targeted GPOs that were configured with user settings enabled and computer settings disabled.

This week we'll find GPOs containing user settings. I'll show you two ways, the second of which is preferred...


Way, the first - Get-GPOReport 

Get-GPO -All | ForEach-Object {
    ([XML](Get-GPOReport -Guid $_.ID -ReportType Xml) | Where-Object {$_.GPO.User.ExtensionData -ne $null}).GPO.Name




What's going on?

  • Get all the GPOs in the current domain with Get-GPO
  • Pipe each found GPO into a ForEach-Object loop
  • Within the ForEach-Object loop execute Get-GPOReport for the current GPO in the pipeline and make the -ReportType XML
  • Cast the resultant string object to [XML] and pipe it into Where-Object
  • Use Where-Object to filter on GPOs with the ExtensionData node present under the User node
  • Display the name of the filtered GPO from the XML object, using dot notation


Way, the second - Get-ADObject 

Think about this. The first way will find policies that have User extension data populated, but also have the User settings disabled. What to do? Well, you could refer to last week's post to find GPOs with both 'User Enabled / Computer Enabled' and 'User Enabled / Computer Disabled' and then pipe these objects into the above loop, i.e. replace Get-GPO -All with these filtered objects. Fair enough.

But, what if the first way also finds policies that used to contain user settings but have since had them removed. Hmmm - that would be trickier to filter out... not insurmountable with the right XML navigation, but definitely trickier...

Let's switch from the GroupPolicy PowerShell module to the ActiveDirectory PowerShell module and take a look at this rather nifty LDAP query...

Get-ADObject -LDAPFilter “(&(objectclass=groupPolicyContainer)(!(flags:1.2.840.113556.1.4.803:=1))(gPCUserExtensionNames=*)(!(gPCUserExtensionNames=' ')))” -SearchBase "cn=Policies,cn=System,dc=halo,dc=net" -Properties DisplayName,gPCUserExtensionNames | Select DisplayName,DistinguishedName,gPCUserExtensionNames




What's going on?

Let's take a look at the components of the LDAP query. The key is the gPCUserExtensionNames attribute which may be present on the Group Policy Containers (GPCs) in Active Directory:

  • (!(flags:1.2.840.113556.1.4.803:=1)) - this excludes GPOs that have the disable user options flags set
  • (gPCUserExtensionNames=*) - this includes GPOs that have the gPCUserExtensionNames set
  • (!(gPCUserExtensionNames=' ')) - this excludes GPOs that have gPCUserExtensionNames set to a single space, i.e. those that used to have user settings but no longer do


To recap - the LDAP query filters out GPOs

  • that have user settings disabled
  • that do not user extension data present
  • that used to contain user settings, but no longer do


I mentioned this is my preferred way. Here's why:

  • LDAP is MUCH faster than running Get-GPO and then Get-GPOReport for all policies
  • I have access to useful properties as I'm dealing with an object representing the GPC rather than an XML report
  • There may be issues with the results of Get-GPOReport depending on a number of factors, e.g. third party extensions