Group Policy Objects (GPOs) can contain many different kinds of settings. Much of that data is simple registry data. Finding registry settings in GPOs and handling them is not the simplest of tasks and requires some PowerShell. Microsoft has provided some cmdlets for the management of Group Policy and at SDM Software we have provided quite a bit more to enable additional scenarios that cannot be achieved out of the box.
Here is an example of using Microsoft’s native Group Policy cmdlets to find registry settings in a GPO. This example looks at the Registry.pol file in the GPO which contains settings from Administrative Templates as well as other settings that write to the registry.pol file.
In this video I will go through finding managed Administrative Template settings in the GP Editor, through a free tool called registry.pol viewer and through a PowerShell Function I created borrowing the core functionality from GPOGuy’s ADMXtoDSC script.
- Registry.pol viewer can be found – SDM Software Free Tools
- ADMXtoDSC script can be found – ADMXtoDSC
- I began converting this to an advanced function. Check that out here – ConvertToDSC
I’m adding the function that I created to go through the GPO and find all settings in registry.pol file. You can easily add capabilities to find all GP Preference Registry Settings as well. You will need to know a bit about how these functions work but watch the video to see a walk-through of this information. It is a bit long but I think you’ll find it useful.
# This function retrieves settings it does not make changes to GPOs. function Recurse-PolicyKeys{ [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string]$GPOName, [Parameter(Mandatory=$true)] [string]$Key ) $current = Get-GPRegistryValue -Name $gpoName -Key $key foreach ($item in $current){ if ($item.ValueName -ne $null){ [array]$returnVal += $item } else{ Recurse-PolicyKeys -Key $item.fullkeypath -gpoName $gpoName } } return $returnVal }
Check-out the video. Enjoy!
Hi Kevin, nice one. Thanks for sharing this.
this is incredibly helpful for me in finding deprecated settings that are no longer visible in ADMX files. DO you know of a way to add the gpo name as a property in the output? Or would I have to create a new array with each setting and add the gponame as a property?
If you create a new custom PSObject, and then use Note Properties, you can essentially build your own output types that contain the information you want. Have a look here for details: https://technet.microsoft.com/en-us/library/hh750381.aspx
I never knew that the Get-GPRegistryValue function returns sub key names, that’s great! Is there any way to return the 1st level key names under the hives? I can’t assume that I would know all possible ‘root’ keys under HKLM & HKCU for every GPO.
Jim-
If you pass one of the 4 top level policy keys to Get-GPRegistryValue, you should get a list from the cmdlet of all the child keys underneath those. For example:
Get-GPRegistryValue -Name “Administrative Template GPO” -Key HKLM\Software\Microsoft\Windows\CurrentVersion\Policies
or
Get-GPRegistryValue -Name “Administrative Template GPO” -Key HKLM\Software\Policies
should get you all the keys under Computer Configuration for that GPO.
I think starting from ‘hklm\software’ will get both. Deployed printers don’t get stored here?
Not completely. HKLM\Software will tell you the next level of keys, but for HKLM\Software\Microsoft\Windows\Currentversion\Policies, you will have to keep drilling down. Given that the 4 policy keys are well-known, that’s why I suggested providing those keys directly. Deployed Printers are defined in AD actually, under the groupPolicyContainer object. You won’t find them in registry.pol.
Is there a way to script deploying printers in powershell without using crazy xml files?
If you’re talking about Deployed Printers, then you just need to create the appropriate AD objects to implement them, and that can be done in PowerShell. If you’re talking about GP Preferences Printers, then you would need to create the XML files.
How would you create the gpo for deployed printers in powershell if it’s not registry entries?
It’s not trivial, but you need to look under the GPC object in AD, on a GPO where those printers have been deployed with GP Editor, and look at the objects that get created there, then mimic that in your PowerShell script using the MS AD module to create the objects and their attributes.
Hmm, I’m really interested in this. I have this. I thought there would be a list of objects in the gpc, but there isn’t. Can it be done with the ms tools? I see $b[0] has an ObjectClass of groupPolicyContainer.
$a = get-gpo ‘add printer (machine)’
$b = get-adobject -filter * -SearchBase ‘cn={A2E00266-0CD7-419B-B772-1DFF02F1F7A8},cn=policies,cn=system,DC=me,DC=com’
Oh, I have to say -properties * to get all the properties. I found a nice script that modifies the printer and server names in a deployed printer gpo. https://www.craig-tolley.co.uk/2014/09/10/modifying-gpo-printer-deployment-using-powershell/
Any idea how to make it work with cmdlet: get-gpprefregistryvalue
So only the Registry.xml is processes from GPP part of GPO
Trying this:
# This function retrieves settings it does not make changes to GPOs.
function Recurse-PolicyKeys-User{
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$GPOName,
[Parameter(Mandatory=$true)]
[string]$Key
)
$current = get-gpprefregistryvalue -Name $gpoName -context user -Key $key
foreach ($item in $current){
if ($item.ValueName -ne $null){
[array]$returnVal += $item
}
else{
Recurse-PolicyKeys -Key $item.fullkeypath -gpoName $gpoName
}
}
return $returnVal
}
works, but I must fill user context at least 4 times:
cmdlet Get-GPPrefRegistryValue at command pipeline position 1
Supply values for the following parameters:
Context: user
OK, this one does it:
# This function retrieves settings it does not make changes to GPOs.
function Recurse-PolicyKeys-User{
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$GPOName,
[Parameter(Mandatory=$true)]
[string]$Key
)
$current = get-gpprefregistryvalue -Name $gpoName -context user -Key $key
foreach ($item in $current){
if ($item.ValueName -ne $null){
[array]$returnVal += $item
}
else{
Recurse-PolicyKeys-User -Key $item.fullkeypath -gpoName $gpoName
}
}
return $returnVal
}
But it often fails on some on my GPOs with error:
The script failed due to call depth overflow.
+ CategoryInfo : InvalidOperation: (0:Int32) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : CallDepthOverflow