Determine What Active Directory Organization Units a Group Policy is Linked to with PowerShell

Have you ever noticed that there's not many GPO related PowerShell cmdlets? I started out wanting to know what group policies existed that weren't linked to OU's and added a few other properties to return additional useful information for the ones that were:

 1#Requires -Version 3.0
 2#Requires -Modules GroupPolicy
 3
 4function Get-GPOLink {
 5
 6<#
 7.SYNOPSIS
 8    Returns the Active Directory (AD) Organization Units (OU's) that a Group Policy Object (GPO) is linked to.
 9
10.DESCRIPTION
11    Get-GPOLink is a function that returns the Active Directory Organization Units (OU's) that a Group Policy
12Object (GPO) is linked to.
13
14.PARAMETER Name
15    The Name of the Group Policy Object.
16
17.EXAMPLE
18    Get-GPOLink -Name 'Default Domain Policy'
19
20.EXAMPLE
21    Get-GPOLink -Name 'Default Domain Policy', 'Default Domain Controllers Policy'
22
23.EXAMPLE
24    'Default Domain Policy' | Get-GPOLink
25
26.EXAMPLE
27    'Default Domain Policy', 'Default Domain Controllers Policy' | Get-GPOLink
28
29.EXAMPLE
30    Get-GPO -All | Get-GPO-Link
31
32.INPUTS
33    System.String, Microsoft.GroupPolicy.Gpo
34
35.OUTPUTS
36    PSCustomObject
37#>
38
39    [CmdletBinding()]
40    param (
41        [Parameter(Mandatory,
42                   ValueFromPipeline,
43                   ValueFromPipelineByPropertyName)]
44        [Alias('DisplayName')]
45        [string[]]$Name
46    )
47
48    PROCESS {
49
50        foreach ($n in $Name) {
51            $problem = $false
52
53            try {
54                Write-Verbose -Message "Attempting to produce XML report for GPO: $n"
55
56                [xml]$report = Get-GPOReport -Name $n -ReportType Xml -ErrorAction Stop
57            }
58            catch {
59                $problem = $true
60                Write-Warning -Message "An error occured while attempting to query GPO: $n"
61            }
62
63            if (-not($problem)) {
64                Write-Verbose -Message "Returning results for GPO: $n"
65
66                [PSCustomObject]@{
67                    'GPOName' = $report.GPO.Name
68                    'LinksTo' = $report.GPO.LinksTo.SOMName
69                    'Enabled' = $report.GPO.LinksTo.Enabled
70                    'NoOverride' = $report.GPO.LinksTo.NoOverride
71                    'CreatedDate' = ([datetime]$report.GPO.CreatedTime).ToShortDateString()
72                    'ModifiedDate' = ([datetime]$report.GPO.ModifiedTime).ToShortDateString()
73                }
74
75            }
76
77        }
78
79    }
80
81}

One of more group policy names can be piped into this function or provided via parameter input. If you want to query all group policy objects, simply pipe Get-GPO -All to it:

gpolink1.png

What's neat to me is being able to create an XML report on the fly, store it in a variable, and query that variable to return the desired output.

µ