Export Group Policy Links with PowerShell

Export Group Policy Links with PowerShell

Hi All,

I’ve come across a Domain, where there are a ton of Group Policies. So i was looking for a way to figure out if the Group Policy is still used. One way to figure out is to check if the Group Policy is linked to an Active Directory OU or Site. There might be still some Group Policys that are not Linked that might be used from time to Time to Test things or used for diffrent Szenarios. But even identifying such not “actively” used Group Policys could help to decrease the amount of Group Policies in that Domain.

PowerShell

As a PowerShell and Scripting Guy i had a look into the GroupPolicy PowerShell Module that comes with the Remote Server Administation Tools (RSAT)

Get-Command -Module GroupPolicy

Let’s get the GPO

$GPO = Get-GPO -Name <GPOName>
$GPO

And use the GPO Object and pipe it to Get-GPOReport commandlet. Now you can find if and where it’s linked.

[xml]$Report = $GPO | Get-GPOReport -ReportType XML
$Report.GPO.LinksTo

Script

I’ve created a Script where you can export a Single or all GPO with the Links.

If a GPO has multiple Links it will create a Line for each Link.

The Script contains a nice Synopsis that creates the Help.

Get-Command .\Export-GPLinks.ps1 -Full

###############################################################################
# Export-GPLinks.ps1
# Version: 1.0
# Date: 2025-05-15
# Author: Andres Bohren
# Description: This script will export all GPO links to a CSV file.
# Some Source code from here https://www.easy365manager.com/get-gpo-links-with-powershell/
###############################################################################
<#
    .SYNOPSIS
    This script will export all GPO links to a CSV file.

    .DESCRIPTION
    This script will export all GPO links to a CSV file.

    .PARAMETER GPOName
    [string]GPOName specifies the name of the GPO to export. If not provided, all GPOs will be exported.

    .LINK
    https://github.com/BohrenAn/GitHub_PowerShellScripts/tree/main/ActiveDirectory/Export-GPLinks.ps1

    .EXAMPLE
    .\Export-GPLinks.ps1 -GPOName <GPOName>
    This will export the GPO links for the specified GPO to a CSV file.

    .\Export-GPLinks.ps1
    This will export all GPO links to a CSV file.
#>

#Parameter
[CmdletBinding()]
Param (
    [parameter(mandatory = $false)][string]$GPOName
)

#Check if the Parameter GPOName is provided
If ($GPOName -ne "")
{
    [Array]$GPOs = Get-GPO -Name $GPOName
    If ($null -eq $GPO)
    {
        Write-Host "GPO not found: $GPOName" -ForegroundColor Red
        Exit
    }
} else {
    Write-Host "No GPO name provided, exporting all GPOs." -ForegroundColor Yellow
    #Get all GPOs
    [Array]$GPOs = Get-GPO -All
}

#Loop through the GPOs and create the CSV Export

#Create the CSV file
$OutputFile = ".\GPLinks.csv"
"Name;LinkPath;ComputerEnabled;UserEnabled;WmiFilter" | Out-File $OutputFile
$TotalGPO = $GPOs.Count
$INT = 0

#Loop through the GPOs
Foreach ($GPO in $GPOs)
{
    $Int = $INT + 1
    $GPODisplayName = $GPO.DisplayName
    Write-Host "Working on: $GPODisplayName [$INT/$TotalGPO]" -ForegroundColor Green
    [xml]$Report = $GPO | Get-GPOReport -ReportType XML
    $Links = $Report.GPO.LinksTo
    If ($Null -ne $Links)
    {
        ForEach($Link In $Links)
        {
            #A Line for each Link
            $Output = $Report.GPO.Name + ";" + $Link.SOMPath + ";" + $Report.GPO.Computer.Enabled + ";" + $Report.GPO.User.Enabled + ";" + $_.WmiFilter.Name
            $Output | Out-File $OutputFile -Append
        }
    } else {
            #No Links
            $Output = $Report.GPO.Name + ";;" + $Report.GPO.Computer.Enabled + ";" + $Report.GPO.User.Enabled + ";" + $_.WmiFilter.Name
            $Output | Out-File $OutputFile -Append
    }
}

Examples

Export all GPOLinks

#Export all GPO Links
.\Export-GPLinks.ps1

Here’s how the Export looks like

#Export a specific GPO with the Links
.\Export-GPLinks.ps1 

Here’s how the Export looks like

Summary

In my case i had about 700 GPO’s and it turned out that over 250 are not linked and therefore could be deleted. Hope this helps.

Regards
Andres Bohren

PowerShell Logo

Windows Logo