Goatee PFE

Blog of Microsoft Premier Field Engineer Ashley McGlone featuring PowerShell scripts for Active Directory.

Dude, where’s my GPO? Using PowerShell to find all of your Group Policy links.

Dude, where’s my GPO? Using PowerShell to find all of your Group Policy links.

  • Comments 18
  • Likes

Stratego Stratego

I only played Stratego once as a kid when I was over at a friend’s house. Strategy, challenge and mystery made the game captivating. A few years ago I bought a vintage 1961 edition on eBay so I could teach my sons to play. As it turns out this game has been around for centuries among various cultures around the world. Pieces are ranked from 1 to 9, with 1 being the most powerful (unless you have a newer edition where the numbers have been revised). The objective is to capture the opponent’s flag while avoiding the bombs hidden among the ranks. By now you are probably wondering what this has to do with PowerShell or Active Directory.  Keep reading and find out.

GPO Scavenger Hunt

Using the Get-GPOReport cmdlet from the Group Policy PowerShell module you can easily create a report of all your Group Policy Objects (GPOs) like this:


PS C:\> Import-Module GroupPolicy
PS C:\> Get-GPOReport -All -ReportType HTML -Path .\GPO.html


This is a great report, but it can be a bit overwhelming.  What if you want a simple spreadsheet listing of the same information?

Back around 2002 I wrote some code for this in VBScript.  You see, back then Group Policy Management Console (GPMC) had not been released yet.  At that time you created GPOs through AD Users and Computers (ADUC).  I was working with Windows 2000 Server designing OUs and GPOs for a large company’s Windows 2000 implementation.  I needed a report to show me where all of these policies were linked, and I also needed to know where inheritance was blocked and where policies were set to “No Override” (now called “Enforced”).  After some recent conversations with peers I decided to rewrite this script in PowerShell.

Understanding GPOs in Active Directory

First off, technically speaking Group Policy is not a feature of Active Directory (AD).  However, so much of the infrastructure rides on AD that most people associate the two.  If you need some help understanding GPOs start here:  Everything you need to get started with Group Policy.

In GPO terms, domains, OUs, and sites are called Scopes of Management (SOMs).  They have an attribute called gPLink that lists all of the GPOs applied to the object.  The gPLink attribute contains a list of GPO distinguished names and a gPLinkOptions value for each one.  This numeric value is a bit switch flagging LinkEnabled status and Enforced status.  SOMs have an attribute call gPOptions which specifies whether Block Inheritance is enabled.  To understand these in more detail you can explore the following links:

Remember that Stratego reference?

imageThe gPLink attribute is a string concatenation that looks something like this:

[LDAP://cn={7BE35F55-E3DF-4D1C-8C3A-38F81F451D86},cn=policies, cn=system,DC=wingtiptoys,DC=local;2][LDAP://cn={046584E4-F1CD-457E-8366-F48B7492FBA2}, cn=policies,cn=system,DC=wingtiptoys,DC=local;0] [LDAP://cn={12845926-AE1B-49C4-A33A-756FF72DCC6B},cn=policies, cn=system,DC=wingtiptoys,DC=local;1]

As you can see, each GPO distinguished name is enclosed with square brackets, and there is a numeric digit following it as described above.  The important point is that GPOs are listed in this string in order of precedence.  In the GPMC GUI you will see multiple linked policies listed top to bottom, 1 through x, with lower numbers winning over higher numbers.  This is just like Stratego.  The #1 policy (Stratego’s marshall) wins over all the others.  Lower numbers always win.

Where’s the PowerShell?

Understanding how policies tie into Active Directory, now you can see that we need a couple targeted LDAP queries to get all of the gPLink and gPOptions attributes from the SOMs.  Then we parse out the attributes and put them into a report.  I am over-simplifying it just a bit, but here are the queries:


# Empty array to hold all possible GPO links            
$gPLinks = @()            
# GPOs linked to the root of the domain            
# !!! Get-ADDomain does not return the gPLink attribute            
$gPLinks += Get-ADObject -Identity (Get-ADDomain).distinguishedName ` 
-Properties name, distinguishedName, gPLink, gPOptions            
# GPOs linked to OUs            
# !!! Get-GPO does not return the gPLink attribute            
$gPLinks += Get-ADOrganizationalUnit -Filter * -Properties name, ` 
distinguishedName, gPLink, gPOptions            
# GPOs linked to sites            
$gPLinks += Get-ADObject -LDAPFilter '(objectClass=site)' ` 
-SearchBase "CN=Sites,$((Get-ADRootDSE).configurationNamingContext)" ` 
-SearchScope OneLevel -Properties name, distinguishedName, gPLink, gPOptions            


Notice in the script comments that Get-ADDomain and Get-GPO do not return the gPLink attribute.  We have to specifically query for this attribute using other cmdlets.  Also notice that I am not filtering out SOMs without a gPLink attribute.  I want to collect all OUs and sites to round out the report, not just the ones with policies linked.

You can download the full script from the TechNet Script Gallery.  The output is a CSV file (gPLink_Report.csv) listing all of the linked policies, their locations, and link configurations.  The report contains the following columns:

  • SOM – Scope of Management, the domain, OU, or site where the policy is linked.  The OUs are tabbed to represent the tree structure for easy viewing.
  • DistinguishedName – Full path to the SOM.
  • BlockInheritance – True if the OU is blocking policy inheritance.  This comes from the gPOptions attribute.
  • LinkEnabled – This is represented by bit 1 of the gPLinkOptions numeric in the gPLink string.
  • Enforced – This is represented by bit 2 of the gPLinkOptions numeric in the gPLink string. This setting is ignored for the policy if not enabled (bit 1).
  • Precedence – Stratego ranking of multiple policies linked to the same SOM.
  • DisplayName – Friendly name of the policy.
  • GPOStatus – All settings enabled. User settings disabled. Computer settings disabled. All settings disabled. Note that this is different than the enabled/disabled status on the gPLink itself.
  • WMIFilter – Name of the WMI filter on the policy, if configured.
  • GUID – The GPO GUID that can be used to identify the policy in ADSIEDIT or the SYSVOL share.
  • PolicyDN – The full path to the group policy container object in Active Directory.

This script has the following prerequisites:

  • PowerShell v2 or above
  • Remote Server Administration Tools (RSAT)
  • AD PowerShell module
  • Group Policy module

Unlike Get-GPOReport this script does NOT include any of the following other related information:

  • Policy filtering by permissions
  • GPOs that are not linked
  • Individual policy settings

With this handy CSV spreadsheet you can easily get an overview of your policies, where they are blocked, and where they are enforced.  Perhaps the helpdesk could use a copy of the script and report when they are troubleshooting group policy calls (in addition to RSOP, of course).

Group Policy Health Check (GPOHC)

As a Microsoft Premier Field Engineer I am part of a global team with many specialties.  Some of my peers are true group policy experts.  You can have one of them visit your company, teach you the ins and outs of group policy, and help optimize your GPOs.  They have many other tricks up their sleeve beyond today’s reporting script.  This service is called the Group Policy Health Check (GPOHC).  Use the links at the bottom of this blog post or contact me for more information if you would like one of these at your company.

The Download

Download today’s script at the TechNet Script Gallery.

UPDATE:  For a new, improved version of this script go to this post.

Can you help me?  Yes!

If you would like to have me or another Microsoft PFE visit your company and assist with the ideas presented in this blog post, then contact your Microsoft Premier Technical Account Manager (TAM) for booking information.

For more information about becoming a Microsoft Premier customer email PremSale@microsoft.com.  Tell them GoateePFE sent you.

Sharing Links
  • Have you used List Object Mode in AD to be able to hide GPOs so that certain SAs could not see them and link them?  Is there any documentation on doing this?

  • Hi Brian,

    We have public documentation on TechNet that describes procedures for List Object Mode in AD, but that is really intended for shared hosting environments rather than tradition customer implementations.

    Have you experimented with "Deny", "Read all properties", "Descendant groupPolicyContainer Objects" on this container "CN=Policies,CN=System,DC=contoso,DC=com"?


  • After applying the group policies , the client machines takes long time to authenticate . Could you please suggest any policy I need to  add/ Review  or is there a minimum policies that I can push to the clients.

  • Hello RGPrakash,

    There are many best practices that can help avoid your issue.  Please see the documents here for more help with Group Policy:




    Ashley McGlone

  • winplat.net/.../List-Group-Policy-Object-using-Powershell.aspx

  • Hey, I would like to get a list of all the GPOs with their respective settings, because I want to know which of our GPOs use scripts.

    What would be the command to get a list of all the GPOs with the settings?


  • Hi Marc,

    You can get a report for that using this command:

    Get-GPOReport -All -ReportType HTML -Path .\GPO.html

    Hope this help,


  • What a great tool. And nice touch adding more underscores to denote the depth of the OUs. Thank you.

  • Hello Ashley,

    I was wondering if there is a way to narrow this report down to a specific OU and it's sub OU's. The reason being is I do not administer my entire domain just a site which they have grouped in an OU. If it's possible thanks for any help you can provide. Have a great day.

  • Ok so I altered the portion where it lists out gpo's linked to OU's and put in -SearchBase "My Top OU DN" that seems to have run without any problems. Thank you for this script it will help me immensely as our organization is trying to standardize it's OU structure. Have a great day.

  • This is a great script. I tried to connect to another domain using a new PS drive, however, the script was not pulling the display name, GPOStatus, or WMIFilter. Any recommendations to do this? I was only getting the DN of the OU and the GUID.

  • Hi Blake, Off the top of my head here are a couple ways to work with this script in a remote domain: 1. Modify every Get-AD* cmdlet in the script with a target server name and credential. Better to convert the script to a function and parameterize these. 2. Open up a PowerShell remoting session to a remote domain server that has the AD cmdlets and run your local copy of the script. Something like this: $s = New-PSSession -ComputerName server1.contoso.com -Credential (Get-Credential) Invoke-Command -Session $s -ScriptBlock {Set-Location c:\temp\} Invoke-Command -Session $s -FilePath .\gPLink_report.ps1 Copy-Item \\server1.contoso.com\c$\temp\gPLink_Report.csv -Destination .\ This should get you started in the right direction. Ashley @GoateePFE

  • Hi,

    Great Script , But can we the Owner and Security filtering details in this script ..

  • Hello Gopi,
    I chose to leave that out to keep it simple. I would suggest using the GPO cmdlets to get that report:
    Get-GPOReport -All -ReportType HTML -Path .\GPO.html

  • Hi Everyone,

    I am looking for a script which givens report of all unlinked GPO's or Orphaned GPO which are not linked to any domains, site. I need to delete all those as a part AD clean up activity

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment