-
Create or Update a Group Policy Using Settings From Another Group Policy Using Microsoft PowerShell
March 18, 2016
Over the course of the past several months, I have had several projects where I needed to create, edit, or fix group policies. A problem I ran into was I only needed a subset of the policy settings (Site to Zone Mappings, Microsoft Office settings). Another problem was corrupt group policies that would not backup. How can I get just the settings I needed into a test group policy? This article shows the script I created to handle those situations.
Yes, I know I can just backup a group policy (GPO), create an empty GPO, and then import the backup into the new GPO. But what if the original GPO is corrupted? Or contains hundreds or thousands of settings, and you only need a small subset of those settings?
Every project I have worked on recently has made me glad I created this script. I recently wrote about troubleshooting Site to Zone Mappings. For that project, the customer had hundreds of settings in the GPO that contained the Site to Zone Mappings I needed to troubleshoot. How could I get just those policy settings and ignore all the rest? Sure, I could have done the backup/create empty/import routine, but then I would have spent hours removing all the other policy settings I did not need.
Enough chit-chat. Let’s get to work.
GPOs are made up of various parts. Preferences are stored in XML files, some settings are stored in INF files, and other settings are stored in a registry.pol file. For the work I have been doing, all the settings I need have been in the registry.pol file (so far).
Find the GPO you need the settings for, go to the Details tab in the Group Policy Management Console (GPMC), and copy the Unique ID, as shown in Figure 1.
Browse the SYSVOL folder. I do it by Start, Run, and typing in the domain name like \domain.tld, as shown in Figure 2.
Double-clicking SYSVOL, as shown in Figure 3.
Then double-click the domain name, then Policies, paste the Unique ID into the Search box, and double-click the found result, as shown in Figure 4.
Depending on if the GPO settings you need are from the Computer Configuration or User Configuration, double-click either Machine or User. For this example, the settings I need are User settings, as shown in Figure 5.
Copy and paste the registry.pol file to a work location, as shown in Figures 6 and 7.
Now you need to use Darren Mar-Elia’s Registry.Pol Viewer Utility to create a CSV file from the registry.pol file.
Start polviewer.exe, browse to the registry.pol file and click Submit, as shown in Figure 8.
Click File, Save to CSV, and save the CSV file to your work location, as shown in Figure 9.
Use your favorite text editor, remove the lines of the policy settings you don’t need, and save the updated file, as shown in Figure 10.
Start an elevated PowerShell session and run the script .\CreateGPO.ps1, as shown in Figures 11 and 12.
Open up GPMC, or refresh GPMC, and the new unlinked GPO shows in the Group Policy Objects node, as shown in Figure 13.
I don’t know about you, but that is MUCH faster than importing an entire GPO and then taking the time to delete the settings that are not needed. Now the GPO can be changed to do what is needed, linked, and tested.
#requires -Module GroupPolicy #region help text <# .SYNOPSIS Creates an unlinked Group Policy Object from an imported CSV file. If the Group Policy Object exists, linked or unlinked, it is updated with the settings from the imported CSV file. .DESCRIPTION Creates an unlinked Group Policy Object from an imported CSV file. The CSV file is created using Darren Mar-Elia's Registry .Pol Viewer Utility https://sdmsoftware.com/gpoguy/gpo-freeware-registration-form/ The Registry.pol files only contain settings from the Administrative Templates node in the Group Policy Management Console. This script is designed for consultants and trainers who may create Group Policies in a lab and need a way to recreate those policies at a customer or training site. The GroupPolicy module is required for the script to run. On a server, Group Policy Management must be installed. On a workstation, RSAT is required. Remote Server Administration Tools for Windows 7 with Service Pack 1 (SP1) http://www.microsoft.com/en-us/download/details.aspx?id=7887 Remote Server Administration Tools for Windows 8 http://www.microsoft.com/en-us/download/details.aspx?id=28972 Remote Server Administration Tools for Windows 8.1 http://www.microsoft.com/en-us/download/details.aspx?id=39296 Remote Server Administration Tools for Windows 10 http://www.microsoft.com/en-us/download/details.aspx?id=45520 .PARAMETER PolicyName Group Policy Name. This is a required parameter. This parameter has an alias of PN. .PARAMETER PolicyType The type of Group Policy settings to import. M - Machine (Computer) C - Machine (Computer) U - User This is a required parameter. This parameter has an alias of PT. Default is Machine. If a Group Policy is to contain both Computer and User settings, there will be two .Pol files. One for Machine (Computer) settings and a separate .Pol file for User settings. Each .Pol file is named Registry.pol. The CSV files will need to be have different names. There will then be two CSV files to import. The script will detect if the Group Policy Name exists and if it does, the next set of settings will be added to the existing script. If the Group Policy Name does not exist, a new Group Policy is created with the imported settings. .PARAMETER CSVFile CSV file created by Registry PolViewer utility. This is a required parameter. The parameter has an alias of CSV. The CSV file will contain either Machine or User policy settings. It should contain both. .EXAMPLE PS C:\PSScript > .\CreateGPO.ps1 -PolicyName "Sample Policy Name" -PolicyType M -CSVFIle C:\PSScript\GPOMSettings.csv Darren's PolViewer.exe utility is used first to create the C:\PSScript\GPOMSettings.csv file. If a Group Policy named "Sample Policy Name" does not exist, a policy will be created using the Machine settings imported from the GPOMSettings.csv file. If a Group Policy named "Sample Policy Name" exists, the policy will be updated using the Machine settings imported from the GPOMSettings.csv file. .EXAMPLE PS C:\PSScript > .\CreateGPO.ps1 -PolicyName "Sample Policy Name" -PolicyType U -CSVFIle C:\PSScript\GPOUSettings.csv Darren's PolViewer.exe utility is used first to create the C:\PSScript\GPOUSettings.csv file. If a Group Policy named "Sample Policy Name" does not exist, a policy will be created using the User settings imported from the GPOUSettings.csv file. If a Group Policy named "Sample Policy Name" exists, the policy will be updated using the User settings imported from the GPOUSettings.csv file. .INPUTS None. You cannot pipe objects to this script. .OUTPUTS No objects are output from this script. This script creates or updates a Group Policy Object. .NOTES NAME: CreateGPO.ps1 VERSION: 1.00 AUTHOR: Carl Webster LASTEDIT: March 18, 2016 #> #endregion #region script parameters [CmdletBinding(SupportsShouldProcess = $False, ConfirmImpact = "None", DefaultParameterSetName = "Machine") ] Param( [parameter(ParameterSetName="Machine",Mandatory=$True)] [parameter(ParameterSetName="User",Mandatory=$True)] [Alias("PN")] [ValidateNotNullOrEmpty()] [String]$PolicyName, [parameter(ParameterSetName="Machine",Mandatory=$True, HelpMessage="Enter M or C for Machine or U for User")] [parameter(ParameterSetName="User",Mandatory=$True, HelpMessage="Enter M or C for Machine or U for User")] [Alias("PT")] [String][ValidateSet("M", "C", "U")]$PolicyType="M", [parameter(ParameterSetName="Machine",Mandatory=$True, HelpMessage="Enter path to CSV file.")] [parameter(ParameterSetName="User",Mandatory=$True, HelpMessage="Enter path to CSV file.")] [Alias("CSV")] [ValidateNotNullOrEmpty()] [String]$CSVFile ) #endregion #region script change log #webster@carlwebster.com #@carlwebster on Twitter #https://www.carlwebster.com #Created on November 7, 2015 #released to the community on 18-Mar-2016 #endregion #region initial variable testing and setup Set-StrictMode -Version 2 If(!(Test-Path $CSVFile)) { Write-Error "$(Get-Date): CSV file $($CSVFile) does not exist.`n`nScript cannot continue" Exit } #endregion #region functions Function SetPolicySetting { Param([string]$Key, [string]$ValueName, [string]$ValueType, $Data) If($Key -eq "" -or $ValueName -eq "" -or $ValueType -eq "" -or $Null -eq $Key -or $Null -eq $ValueName -or $Null -eq $ValueType) { #failure Write-Warning "$(Get-Date): Missing data: `nKey: $($Key) `nValueName: $($ValueName) `nValueType: $($ValueType) `nData: $($Data)`n`n" } Else { #Specifies the data type for the registry-based policy setting. You can specify one of the following data #types: String, ExpandString, Binary, DWord, MultiString, or Qword. $NewType = "" $NewData = "" Switch ($ValueType) { "REG_DWORD" {$NewType = "DWord"; $NewData = Invoke-Expression ("0x" + $Data)} "REG_SZ" {$NewType = "String"; $NewData = $Data} "REG_EXPAND_SZ" {$NewType = "ExpandString"; $NewData = $Data} "REG_BINARY" {$NewType = "Binary"; $NewData = $Data} "REG_MULTI_SZ" {$NewType = "MultiString"; $NewData = $Data} "REG_QDWORD" {$NewType = "QWord"; $NewData = Invoke-Expression ("0x" + $Data)} } If($PolicyType -eq "M" -or $PolicyType -eq "C") { $NewKey = "HKLM\$($Key)" } ElseIf($PolicyType -eq "U") { $NewKey = "HKCU\$($Key)" } $results = Set-GPRegistryValue -Name $PolicyName -key $NewKey -ValueName $ValueName -Type $NewType -value $NewData -EA 0 If($? -and $Null -ne $results) { #success Write-Host "$(Get-Date): Successfully added: $($NewKey) $($ValueName) $($NewType) $($NewData)" } Else { #failure Write-Warning "$(Get-Date): Problem adding: $($NewKey) $($ValueName) $($NewType) $($NewData)" } } } #endregion Write-Host "Processing $($PolicyName) Group Policy Object" $results = Get-GPO -Name $PolicyName -EA 0 If($? -and $results -ne $Null) { #gpo already exists Write-Host Write-Host "$(Get-Date): $($PolicyName) exists and will be updated" Write-Host } ElseIf(!($?) -and $results -eq $Null) { #gpo does not exist. Create it $results = New-GPO -Name $PolicyName -EA 0 If($? -and $results -ne $null) { #success Write-Host Write-Host "$(Get-Date): $($PolicyName) does not exist and will be created" Write-Host } Else { #something went wrong Write-Error "$(Get-Date): Unable to create a GPO named $($PolicyName).`n`nScript cannot continue" Exit } } Else { #error Write-Error "$(Get-Date): Error verifying if GPO $($PolicyName) exists or not.`n`nScript cannot continue" Exit } Write-Host "$(Get-Date): Read in CSV file" Write-Host $Settings = Import-CSV $CSVFile If($? -and $Settings -ne $Null) { #success Write-Host "$(Get-Date): Setting policy settings" Write-Host ForEach($Setting in $Settings) { SetPolicySetting $Setting.'Registry Key' $Setting.'Registry Value' $Setting.'Value Type' $Setting.Data } } ElseIf($? -and $Settings -eq $Null) { #success but no contents Write-Warning "$(Get-Date): CSV file $($CSVFile) exists but has no contents.`n`nScript cannot continue" Exit } Else { #failure Write-Error "$(Get-Date): Error importing CSV file $($CSVFile).`n`nScript cannot continue" Exit } Write-Host Write-Host "$(Get-Date): Successfully created/updated GPO $($PolicyName)" Write-Host Get-GPO -Name $PolicyName
Thanks
Webster
8 Responses to “Create or Update a Group Policy Using Settings From Another Group Policy Using Microsoft PowerShell”
Leave a Reply
April 23, 2020 at 10:25 pm
Hey Carl, this script is excellent. Great way to add 500+ exclusions to Windows Defender configuration via GPO. Thanks, Steve
April 24, 2020 at 6:29 am
Thanks for the shout out. I am glad you find the script as useful as I do.
Thanks
Webster
April 3, 2019 at 11:19 pm
Hi Webster,
Excellent work and script. Actually i am looking for a solution to import the settings from a test GPO into existing GPO (production) and ofcourse it should not remove existing settings, just insert new settings. Is there any way can do that?
The reason is I want to avoid someone incorrectly or wrongly edit for the existing GPO settings based on new Test GPO settings.
April 18, 2019 at 6:12 am
I have not found a way to do that. I created a test GPO and configured a few settings like event logs and Network List Manager Policies. I then imported the settings from my Lab Defaults GPO, and all that remained in the test GPO were the settings from the Lab Defaults GPO.
Maybe the GPO PoSH cmdlets from SDM SOftware will allow you to do what you need.
From the Microsoft docs on the Import Settings Wizard:
“…Follow the instructions in the Import Settings Wizard to select a GPO backup, import its policy settings to replace those in the destination GPO…”
Webster
April 23, 2019 at 10:27 am
Just came across this. I haven’t tested it yet.
Finally! Copy and merge GPOs! PowerShell saves the day!
Webster
November 14, 2018 at 10:40 am
I am new for windows and working on a lab project, and this is very helpful in creating or updating a GPO from CSV. But I have a request, when I executed this script I found that security setting are not imported to new GPO only administrative template got imported. Is there any way to import security settings also
November 14, 2018 at 1:29 pm
Security settings are handled differently.
Understanding Group Policy Storage
Webster
March 19, 2016 at 6:27 am
Brilliant script Webster!
I have been using a modified version of Ashley McGlone’s GPFunctions.ps1 script to assist with this task to date:
https://gallery.technet.microsoft.com/scriptcenter/Copy-and-Merge-Group-918af45a
I’ll give yours a go 🙂
Cheers,
Jeremy