Find and delete unlinked (orphaned) GPOs with PowerShell

In this post, I will discuss a PowerShell script that helps you find and delete unlinked Group Policy Objects (GPO), also known as orphaned GPOs. Orphaned GPOs are not linked to any Active Directory sites, domains, or organizational units (OUs). This can cause various problems. Using PowerShell, it is easy to create reports of unlinked GPOs, back them up, and eventually delete them.

Update: The method discussed in this post only works for GPOs that are linked to OUs because Get-GPOReport isn't able to handle Site-linked GPOs. Don't use the script if you have Site-linked GPOs!

What causes orphaned GPOs? ^

Many admins extensively test GPOs before implementing them. Sometimes they simply unlink a test GPO instead of deleting it. Policies continuously change in most networks. If certain policies become obsolete, admins tend to just unlink them because the corresponding policies might become relevant again at a later time.

In my experience, this happens quite often, and many admins don't really care about unlinked GPOs. They just create new GPOs over and over again until nobody has any idea which GPOs are still used and which became orphaned years ago.

After years of changes, depending on the complexity of your environment, you may have hundreds or even thousands of unlinked GPOs. This leads to performance issues and messes up your GPO infrastructure. In can confuse adminsand lead to configuration errors.

Who wants to go through all these GPOs in the Group Management Console (GPMC) to find orphaned GPOs and delete them? Fortunately, PowerShell makes it relatively easy to automate the GPO cleanup process or just send notifications if GPOs become orphaned.

Finding unlinked GPOs with PowerShell ^

If you link GPOs to Sites you couldn’t use this method, as it is described in this post. If you want to use this method, you have to exclude Site linked GPOs based on a filter that identify those. It could be based on a Naming convention.

To find unlinked GPOs, we will use the Get-GPO and Get-GPOReport commands, which belong to the Group Policy module that is a part of RSAT. You can import the module with this command:

To retrieve all GPOs, we use the -All parameter and use Get-GPOReport to cast them to an XML object. We pipe the result to Select-String, which finds us all lines without "<LinkTo>".

The following command creates a list of all unlinked GPOs:

Get unlinked GPOs

Get unlinked GPOs

To log these GPOs to a text file, you just have to add this line after $_.DisplayName:

We will use it later to log GPOs.

Deleting GPOs with PowerShell ^

Because you might not want to delete GPOs before creating a backup, we need a variable for our backup location.

The next command creates the backup:

To create a report of unlinked GPOs, we have to use Get-GPOReport again. However, instead of using XML, we will set the ReportType to HTML.

As the last step, we delete those GPOs using the Remove-GPO cmdlet:

Let´s put all of these parts together. The only thing I added is a $Date variable to identify backups from different days.

Example of GPO backup and reports

Example of GPO backup and reports

You can run this script as a scheduled task to automate GPO cleanup.

If you simply want to create a report without automatically removing GPOs, you can remove $_.Displayname | remove-gpo –Confirm from the command. You can then check your backup location to take a closer look at orphaned GPOs. You can also send e-mails that inform you about new, unlinked GPOs. This is accomplished with the Send-MailMessage cmdlet that I added at the end of the script.

Conclusion ^

I highly recommend cleaning up your Group Policy environment regularly to reduce complexity and simplify the work of Group Policy admins for your network. I hope my script helps you automate this task!

Join the 4sysops PowerShell group!

Your question was not answered? Ask in the forum!

  1. Vincent 2 years ago


    I ran this script (without deleting GPOs), it reported some GPOs as non-linked, but in fact, those are linked to AD sites, not OU.

    So if had included the delete command, i would have deleted active GPOs ...

    Would you mind having a look at it please ?



  2. Author

    Hi Vincent,

    using Get-GPOReport doesn´t include Sites. You can use the mentioned method, if you linking GPOs to a domain or OUs. If you want to use it, you have to exlclude site-linked GPOs based on naming or searching for those and compare them.


    • Vincent 2 years ago


      Thanks for your reply.

      I was asking just to be sure i was using your script the right way.




  3. devi 1 year ago

    When I use the Following script it giving an error

    "Cannot validate argument on parameter 'Name'. The argument is null or empty"

    I am giving input file  as I need particular GPOs needs to back up not all in domain


    • Hi Devi

      Could you please check the current content of E:\GPO\GPONames.txt.
      From the error message the only inference that can be drawn is, it contains some whitespace at the beginning of the file.


  4. devi 1 year ago

    Thanks.. its working now


  5. Gururaj 1 year ago

    where the links are preserved if I use -keeplinks when the GPO itself is deleted.


  6. Bernd 10 months ago

    HRESULT: 0x80072035)

    by accident i deleted 'default domain policy'

    orphaned and missing.


  7. Simon Smith 1 month ago

    There is an enterprise level tool called Gytpol Validator which does this on all endpoints in an organization


Leave a reply

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


© 4sysops 2006 - 2020


Please ask IT administration questions in the forums. Any other messages are welcome.


Log in with your credentials


Forgot your details?

Create Account