Carl Webster Accessibility Statement

Carl Webster is committed to facilitating the accessibility and usability of its website, carlwebster.com, for everyone. Carl Webster aims to comply with all applicable standards, including the World Wide Web Consortium’s Web Content Accessibility Guidelines 2.0 up to Level AA (WCAG 2.0 AA). Carl Webster is proud of the efforts that we have completed and that are in-progress to ensure that our website is accessible to everyone.

If you experience any difficulty in accessing any part of this website, please feel free to email us at info@carlwebster.com and we will work with you to provide the information or service you seek through an alternate communication method that is accessible for you consistent with applicable law (for example, through telephone support).

  • Create or Update a Group Policy Using Settings From Another Group Policy Using Microsoft PowerShell

    March 18, 2016

    Active Directory, PowerShell

    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.

    Figure 1
    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.

    Figure 2
    Figure 2

    Double-clicking SYSVOL, as shown in Figure 3.

    Figure 3
    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.

    Figure 4
    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.

    Figure 5
    Figure 5

    Copy and paste the registry.pol file to a work location, as shown in Figures 6 and 7.

    Figure 6
    Figure 6
    Figure 7
    Figure 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.

    Figure 8
    Figure 8

    Click File, Save to CSV, and save the CSV file to your work location, as shown in Figure 9.

    Figure 9
    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.

    Figure 10
    Figure 10

    Start an elevated PowerShell session and run the script .\CreateGPO.ps1, as shown in Figures 11 and 12.

    Figure 11
    Figure 11
    Figure 12
    Figure 12

    Open up GPMC, or refresh GPMC, and the new unlinked GPO shows in the Group Policy Objects node, as shown in Figure 13.

    Figure 13
    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.

    Here is the script.

    #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







    About Carl Webster

    Webster is a Sr. Solutions Architect for Choice Solutions, LLC and specializes in Citrix, Active Directory and Technical Documentation. Webster has been working with Citrix products for many years starting with Multi-User OS/2 in 1990.

    View all posts by Carl Webster

    8 Responses to “Create or Update a Group Policy Using Settings From Another Group Policy Using Microsoft PowerShell”

    1. Steve Says:

      Hey Carl, this script is excellent. Great way to add 500+ exclusions to Windows Defender configuration via GPO. Thanks, Steve

      Reply

    2. Junz Tan Says:

      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.

      Reply

      • Carl Webster Says:

        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

        Reply

      • Carl Webster Says:

        Just came across this. I haven’t tested it yet.

        Finally! Copy and merge GPOs! PowerShell saves the day!

        Webster

        Reply

    3. Vivek Says:

      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

      Reply

    4. Jeremy Saunders Says:

      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

      Reply

    Leave a Reply