How many GPOs do you have in your domain?* How many settings do you have configured? If you needed to find every GPO with a certain setting, could you easily do it? In this guide, we are going to cover two ways that you can search Group Policy in your domain.
Method 1: Searching GPOs with the GUI
Launch the GPMC, right click on your Forest, and select Search. From here, you can search for GPOs, links, and even certain CSE settings (like all GPOs with a printer in them). I used Group Policy for several years before someone showed me this search feature. Completely blew me away!
There are two downsides to this search feature. First, User Configuration searching will not work on Windows 8+ machines. Second, you can’t search for specific settings (like all GPOS with a specific printer in them).
Method 2: Searching Group Policy with PowerShell
Back in 2009, Microsoft’s Group Policy team posted a PowerShell script that lets you find specific group policy settings. Like the GUI search, you can also use it to find all GPOs with certain CSEs. But it can also dive into each GPO and find specific settings, configuration, etc. To get started, download and extract the SearchGPOsForSetting script. In the comments, you will see two links and several examples to help you.
Let’s say that you want to find all GPOs that have the Administrative Template Run these programs at user logon set to Enabled. You would start by looking up the CSE extension name. Right click on any GPO with a configured administrative template in it. Select Save Report and change the Save as Type to XML.
Open the saved report in Notepad and search for the configured setting. In the extension line, the last value is the extension that you will search by. The screenshot below shows that Administrative Templates use the Registry extension.
Now that we know our extension, we can launch PowerShell ISE and search for our specific setting. Our search will look like:
.\SearchGPOsForSetting.ps1 -IsComputerConfiguration $true -Extension Registry -where Name -is “Run these programs at user logon” -Return State
After a few minutes, our results will look like:
By using these two methods, you should be able to find any Group Policy setting or configuration in your environment! If you have any issues with the script (or questions), just leave a comment below. If you are ever needing to find out more information on a specific setting, you can use this GPSearch guide.
*PowerShell way to count GPOS: (Get-GPO -all).count
Here is the script content as well:
# SearchGPOsForSetting.ps1 # # http://blogs.technet.com/b/grouppolicy/archive/2009/04/14/tool-images.aspx # http://blogs.technet.com/b/grouppolicy/archive/2009/04/17/find-settings-in-every-gpo.aspx # # Powershell script that does the following: # SearchGPOsForSetting.ps1 [–IsComputerConfiguration] <boolean> [-Extension] <string> # [-Where] </string><string> [-Is] </string><string> [[-Return] </string><string>] [[-DomainName] </string><string>] # [-Verbose] [-Debug] [-ErrorAction <actionpreference>] [-WarningAction </actionpreference><actionpreference>] # [-ErrorVariable <string>] [-WarningVariable </string><string>] [-OutVariable </string><string>] [-OutBuffer <int32>] # # Example: .\SearchGPOsForSetting.ps1 -IsComputerConfiguration $true -Extension Security -Where Name -Is LockoutDuration -Return SettingNumber # Example: .\SearchGPOsForSetting.ps1 -IsComputerConfiguration $true -Extension Registry -Where Name -Is ACSettingIndex -Return SettingNumber # Example: .\SearchGPOsForSetting.ps1 -IsComputerConfiguration $true -Extension SoftwareInstallation -where AutoInstall -is true -Return Path # Example: .\SearchGPOsForSetting.ps1 -IsComputerConfiguration $true -Extension Registry -where Name -is "Run these programs at user logon" -Return State param ( [Parameter(Mandatory=$true)] [Boolean] $IsComputerConfiguration, [Parameter(Mandatory=$true)] [string] $Extension, [Parameter(Mandatory=$true)] [string] $Where, [Parameter(Mandatory=$true)] [string] $Is, [Parameter(Mandatory=$false)] [string] $Return, [Parameter(Mandatory=$false)] [string] $DomainName = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() ) function print { param ( $displayName, $value ) $host.UI.WriteLine(); $stringToPrint = "The Gpo '" + $displayName + "' has a " + $Extension + " setting where '" + $Where + "' is equal to '" + $Is + "'"; if ($Return -ne $null) { $stringToPrint += " and the value of its '" + $Return + "' property is: '" + $value + "'"; } $host.UI.Write([ConsoleColor]::Magenta, [ConsoleColor]::Black, $stringToPrint); $host.UI.WriteLine(); } function processNodes { param ( $nodes, $foundWhere ) $thePropertyWeWant = $Where; # If we already found the $Where then we are looking for our $Return value now. if ($foundWhere) { $thePropertyWeWant = $Return; } foreach($node in $nodes) { $valueWeFound = $null; #Here we are checking siblings $lookingFor = Get-Member -InputObject $node -Name $thePropertyWeWant; if ($lookingFor -ne $null) { $valueWeFound = $node.($lookingFor.Name); } else #Here we are checking attributes. { if ($node.Attributes -ne $null) { $lookingFor = $node.Attributes.GetNamedItem($thePropertyWeWant); if( $lookingFor -ne $null) { $valueWeFound = $lookingFor; } } } if( $lookingFor -ne $null) { #If we haven't found the $Where yet, then we may have found it now. if (! $foundWhere) { # We have found the $Where if it has the value we want. if ( [String]::Compare($valueWeFound, $Is, $true) -eq 0 ) { # Ok it has the value we want too. Now, are we looking for a specific # sibling or child of this node or are we done here? if ($Return -eq $null) { #we are done, there is no $Return to look for print -displayName $Gpo.DisplayName -value $null; return; } else { # Now lets look for $Return in the siblings and then if no go, the children. processNodes -nodes $node -foundWhere $true; } } } else { #we are done. We already found the $Where, and now we have found the $Return. print -displayName $Gpo.DisplayName -value $valueWeFound; return; } } if (! [String]::IsNullOrEmpty($node.InnerXml)) { processNodes -nodes $node.ChildNodes -foundWhere $foundWhere; } } } #Import our module for the call to the Get-GPO cmdlet Import-Module GroupPolicy; $allGposInDomain = Get-GPO -All -Domain $DomainName; $xmlnsGpSettings = "http://www.microsoft.com/GroupPolicy/Settings"; $xmlnsSchemaInstance = "http://www.w3.org/2001/XMLSchema-instance"; $xmlnsSchema = "http://www.w3.org/2001/XMLSchema"; $QueryString = "gp:"; if($IsComputerConfiguration){ $QueryString += "Computer/gp:ExtensionData/gp:Extension"; } else{ $QueryString += "User/gp:ExtensionData/gp:Extension"; } foreach ($Gpo in $allGposInDomain) { $xmlDoc = [xml] (Get-GPOReport -Guid $Gpo.Id -ReportType xml -Domain $Gpo.DomainName); $xmlNameSpaceMgr = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable); $xmlNameSpaceMgr.AddNamespace("", $xmlnsGpSettings); $xmlNameSpaceMgr.AddNamespace("gp", $xmlnsGpSettings); $xmlNameSpaceMgr.AddNamespace("xsi", $xmlnsSchemaInstance); $xmlNameSpaceMgr.AddNamespace("xsd", $xmlnsSchema); $extensionNodes = $xmlDoc.DocumentElement.SelectNodes($QueryString, $XmlNameSpaceMgr); foreach ($extensionNode in $extensionNodes) { if ([String]::Compare(($extensionNode.Attributes.Item(0)).Value, "http://www.microsoft.com/GroupPolicy/Settings/" + $Extension, $true) -eq 0) { # We have found the Extension we are looking for now recursively search # for $Where (the property we are looking for a specific value of). processNodes -nodes $extensionNode.ChildNodes -foundWhere $false; } } }
I got the following error when attempting to run the script. This was easily resolved by adding the closing ) on lines 6, 8 & 10.
At C:\Users\DSampson01\Documents\SearchGPOsForSetting.ps1:6 char:27
+ [Parameter(Mandatory=$true]
+ ~
Missing closing ‘)’ in expression.
At C:\Users\DSampson01\Documents\SearchGPOsForSetting.ps1:8 char:27
+ [Parameter(Mandatory=$true]
+ ~
Missing closing ‘)’ in expression.
At C:\Users\DSampson01\Documents\SearchGPOsForSetting.ps1:10 char:28
+ [Parameter(Mandatory=$false]
+ ~
Missing closing ‘)’ in expression.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : MissingEndParenthesisInExpression
Thanks! I fixed a few things with that script.
I get the following error, please help?
Get-GPOReport : Object reference not set to an instance of an object.
At C:\Users\ward118\Downloads\SearchGPOsForSetting\SearchGPOsForSetting.ps1:150 char:22
+ $xmlDoc = [xml] (Get-GPOReport -Guid $Gpo.Id -ReportType xml -Domain $Gpo.Do …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-GPOReport], NullReferenceException
+ FullyQualifiedErrorId : System.NullReferenceException,Microsoft.GroupPolicy.Commands.GetGpoReportCommand
Is this a new feature in 2012?
Nope. The search feature is available to at least 2008.
Can’t seem to get this to work. I try the following:
.\SearchGPOsForSetting.ps1 -IsComputerConfiguration $true -extension registry -where Name -is “DNS Suffix Search List”
but get:
Get-Member : Cannot validate argument on parameter ‘Name’. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At C:\Scripts\PowerShell\SearchGPOsForSetting.ps1:75 char:59
+ … $lookingFor = Get-Member -InputObject $node -Name $thePropertyWeWant;
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-Member], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.GetMemberCommand
I get this same result as well. Does someone have a solution?