The PowerShell script I discuss in this post creates a Group Policy backup in a different way than with the Backup-GPO cmdlet of the Group Policy module. With my function, it will be much easier to identify the correct Group Policy Object (GPO) in case you have to restore Group Policy settings.

Let's take a quick peek at the GPO-specific cmdlets included in the GroupPolicy module from Microsoft.

PS C:\> get-command -noun gpo

CommandType     Name                     Version    Source
-----------     ----                     -------    ------
Cmdlet          Backup-GPO               1.0.0.0    GroupPolicy
Cmdlet          Copy-GPO                 1.0.0.0    GroupPolicy
Cmdlet          Get-GPO                  1.0.0.0    GroupPolicy
Cmdlet          Get-GPOReport            1.0.0.0    GroupPolicy
Cmdlet          Import-GPO               1.0.0.0    GroupPolicy
Cmdlet          New-GPO                  1.0.0.0    GroupPolicy
Cmdlet          Remove-GPO               1.0.0.0    GroupPolicy
Cmdlet          Rename-GPO               1.0.0.0    GroupPolicy
Cmdlet          Restore-GPO              1.0.0.0    GroupPolicy

Performing a backup using Backup-GPO

Let's a take a backup of a single GPO and see what the output looks like.

Backup-GPO -name "Default Domain Policy" - path c:\temp\gpobackup
Backup GPO output

Backup GPO output

I asked the cmdlet to back up the GPO named "Default Domain Policy." The cmdlet created a folder that contains all the relevant parts of the GPO. However, the folder's name is not "Default Domain Policy." Instead it is named after the BackupID created for the GPO.

The BackupID is a 32-bit identifier that is unique for each backup. Its name matches the name of the folder containing the backup copy of the GPO. Microsoft does this so you can take multiple backups of the same GPO, save them in a common location, and separate them for later retrieval.

BackupID is unwieldy to work with in my opinion, especially if you are backing up more than one GPO. In fact, I would bet the default behavior most admins do is to backup GPOs in bulk on a regular schedule. Imagine saving a few copies of your GPOs to the same folder by BackupID and then trying to figure out which GPO is which. It is impossibly hard to manage. In this scenario, you end up with just a giant list of folders with unintelligible GUIDs.

Backup GPO output of many GPOS

Backup GPO output of many GPOS

My solution

I got frustrated with this approach and set out to make a better backup that lists my backups by GPO name instead of BackupID. However, Microsoft still requires the BackupID for restoring the GPO at a later date, so I decided to append the GPO Name to the folder created by Microsoft's Backup-GPO cmdlet. This gives me the best of both worlds: the GPO name and the BackupID.

Since I am still using the Microsoft cmdlets to do the work, I will need to read the GPO info, backup the GPO, and finally append the GPO name with a delimiter to the newly created folder after the backup of each GPO occurs.

Finally, I want all the GPOs saved in a folder named after the backup date. For example, if I was backing up my GPOs to a network share named Group-Policy, I want a folder created called 2019-01-05 and then a subfolder for each GPO. Here's a screenshot of how it would look:

Desired Folder Layout

Desired folder layout

For me to back up all GPOs, I would have to run the cmdlet Backup-GPO -all. The -all parameter requires a backup path and the domain name that the Group Policies are a part of. You can also specify the server, but it is not a requirement. I'll create a function called Backup-GroupPolicy to back up all GPOs. The function will have parameters for the backup path and for the server to back up the GPOs from.

I also read the domain info and save it to a variable. I'll name these variables $Path, $Server, and $Domain. $Server is not the greatest name. Since we really need the name of a domain controller (DC) for the cmdlet to work, $DC would be better. But Microsoft used ‑Server instead of -DC or -DomainController in their cmdlet, so I will follow suit as well in my function to be consistent and avoid confusion.

The first thing I need to do is read the current GPOs and store the info so I can manipulate it later on:

$GPOInfo = Get-GPO -All -Domain $domain -Server $Server

Then I will need to create a folder to save the GPO backups to. Remember, I have the $path variable that contains the backup path.

#Create a date-based folder to save Group Policy backups
$Date = Get-Date -UFormat "%Y-%m-%d"
$UpdatedPath = "$path\$date"
New-item $UpdatedPath -ItemType directory | Out-Null

I am using Out-Null after I create the folder to hide the output normally shown after the creation of a new folder. At this point, I have my GPO info stored in a variable and a date-based folder to save my backups to. Now I need to perform the backup and manipulate the default GPO backup settings.

The process I'll be following is pretty simple. A loop will perform a backup of each GPO one at a time. The backup will write the data to the location specified in the $UpdatedPath variable and simultaneously save the backup metadata to some temp variables. After the backup of a GPO finishes, the process will then append the name of the GPO to the folder just created. That process will continue for each GPO in my domain.

ForEach ($GPO in $GPOInfo) {

            #Assign temp variables for various parts of GPO data
            Write-Host "Backing up GPO named: " $GPO.Displayname
            $BackupInfo = Backup-GPO -Name $GPO.DisplayName -Domain $Domain  path $UpdatedPath -Server $Server
            $GpoBackupID = $BackupInfo.ID.Guid
            $GpoGuid = $BackupInfo.GPOID.Guid
            $GpoName = $BackupInfo.DisplayName
            $CurrentFolderName = $UpdatedPath + "\" + "{"+ $GpoBackupID + "}"
            $NewFolderName = $UpdatedPath + "\" + $GPOName

            #Rename the newly created GPO backup subfolder from its GPO ID to the GPO Displayname + GUID
            rename-item $CurrentFolderName -newname $NewFolderName

The backup script

Now's let's put all of these bits together into a complete script:

function Backup-GroupPolicy {
<#
    .SYNOPSIS
    Backs up all existing Group Policies to a folder

    .DESCRIPTION
    Backs up all Group Policies to a folder named after the current date. Each group policy is saved in
    its own sub folder. The folder name will be the name of the Group Policy.

    Folder Name Example:
    --------------------
    C:\GPBackup\2018-12-21\Default Domain Policy


    .PARAMETER Path
    Specifies the path where the backups will be saved. The path can be a local folder or a network based folder.
    This is a required parameter. Do not end the path with a trailing slash. A slash at the end will cause an error!

    Correct format:
    c:\backups or \\server\share

    Incorrect Format:
    c:\Backups\ or \\server\share\

    .PARAMETER Domain
    Specifies the domain to look for Group Policies. This is auto populated with the domain info from the PC running
    the cmdlet.

    .PARAMETER Server
    Specifies the Domain Controller to query for group Policies to backup

    .EXAMPLE
    Backup-GroupPolicy -path C:\Backup

    Description:
    This example creates a backup of the GPO's and saves them to the c:\backup folder.
    Since no server was specified, the code will search for the nearest Domain Controller.

    .EXAMPLE
    Backup-GroupPolicy -path C:\Backup -Domain nwtraders.local -Server DC01

    Description:
    This example creates a backup of GPO's in the nwtraders.local domain to the C:\Backup folder.
    The backups will be pulled from the DC named DC01.


    .NOTES
    Name       : Backup-GroupPolicy.ps1
    Author     : Mike Kanakos
    Version    : 1.1.0
    DateCreated: 2018-12-19
    DateUpdated: 2019-01-25

    .LINK
    https://github.com/compwiz32/PowerShell
#>

[CmdletBinding(SupportsShouldProcess=$true)]
param (
    [Parameter(Mandatory=$True,Position=0)]
    [string]
    $Path,

    [Parameter()]
    [string]
    $Domain = (Get-WmiObject Win32_ComputerSystem).Domain,

    [Parameter()]
    [string]
    $Server
    )

    begin {

        # Get current GPO information
        $GPOInfo = Get-GPO -All -Domain $domain -Server $Server


        #Create a date-based folder to save backup of group policies
        $Date = Get-Date -UFormat "%Y-%m-%d"
        $UpdatedPath = "$path\$date"

        New-item $UpdatedPath -ItemType directory | Out-Null

        Write-Host "GPO's will be backed up to $UpdatedPath" -backgroundcolor white -foregroundColor red
    } #end of begin block

    process {

        ForEach ($GPO in $GPOInfo) {

            Write-Host "Backing up GPO named: " -foregroundColor Green -nonewline
            Write-Host $GPO.Displayname -foregroundColor White

            #Assign temp variables for various parts of GPO data
            $BackupInfo = Backup-GPO -Name $GPO.DisplayName -Domain $Domain -path $UpdatedPath -Server $Server
            $GpoBackupID = $BackupInfo.ID.Guid
            $GpoGuid = $BackupInfo.GPOID.Guid
            $GpoName = $BackupInfo.DisplayName
            $CurrentFolderName = $UpdatedPath + "\" + "{"+ $GpoBackupID + "}"
            $NewFolderName = $UpdatedPath + "\" + $GPOName + "___" + "{"+ $GpoBackupID + "}"
            $ConsoleOutput = $GPOName + "___" + "{"+ $GpoBackupID + "}"

            #Rename the newly created GPO backup subfolder from its GPO ID to the GPO Displayname + GUID
            rename-item $CurrentFolderName -newname $NewFolderName


        } #End ForEach loop

    } #End of process block

    end {
    } #End of End block
} #End of function

You can run this function as needed or schedule it to run regularly via a scheduled task or a scheduled job. Once scheduled, it's one less thing you have to perform manually each month. If you work at a company that uses GPOs heavily, this function may take a good bit of time to run. I have approximately 150 GPOs in my employer's domain, and the script takes just a few short minutes to complete. The script will show the name of each GPO it's backing up when running it, so you can get an idea of how much work it has completed.

Script output in progress

Script output in progress

Conclusion

I built this function because I was not happy with the default output from the built-in Microsoft tools. That's what makes PowerShell so great: if something doesn't work as expected, you can build your own tool! My hope is that this tool will become a useful addition in your sysadmin arsenal. Be on the lookout for a follow-up article that walks you through the restore process using a script I wrote that was designed to do restores specifically from the backups created by this tool.

Subscribe to 4sysops newsletter!

Last but not least, all my scripts are constantly under revision as I find new ways to improve them. You can find the latest version of all my scripts at my Github PowerShell repo. Let me know what you think in the comment section below. Thanks for reading!

avataravataravataravatar
37 Comments
  1. Michael Webber 4 years ago

    I see on line 91, the hyphen is missing from path.  It should be -path.

    • Author
      Mike Kanakos (Rank 3) 4 years ago

      Interesting and good find!!!
      It’s there in the original content; it must have been removed by accident somewhere along the way in the publishing process. I have corrected it. Thanks for taking the time to point it out so it can be fixed.

    • That was my bad. Must have happened when I edited the text. However, I have no idea how because I just copy and pasted the code.

      avatar
  2. Fabian Niesen 4 years ago

    I had the same thoughts in 2014, that’s the reason why I wrote my GPOBackups script and shared it at the Technet Gallary since this time. Meanwhile, including retention period, Eventlog entries, filtering for nonusable characters and HTML-Reports.

    If you like to take look for some extensions: bit.ly/gpobackup

    avataravatar
  3. I never thought that having to deal with GUIDs could be an issue.
    That’s probably because I never had to restore GPOs until now… 😉

    Thanks for the post!

    avatar
    • Author
      Mike Kanakos (Rank 3) 4 years ago

      Luc,

      I did a small re-write of the script to fix a bug that prevented restores from happening correctly. The article is updated with the revamped code or you can get it here. However, You will need my corresponding Restore-GroupPolicy script to make the restores work properly.

      avatar
  4. Jamie Cottrell 4 years ago

    For me I could not get restores to work using this script. I updated the foreach loop to the following:

    ForEach ($GPO in $GPOInfo) {

    $BackupFolder = New-Item $UpdatedPath\$($GPO.Displayname) -ItemType directory
    #Assign temp variables for various parts of GPO data
    Write-Host “Backing up GPO named: ” $GPO.Displayname
    Backup-GPO -Name $GPO.DisplayName -Domain $Domain -path $BackupFolder.FullName -Server $Server

    } #End ForEach loop

    Now this is wokring for getting the restore GPO to work correctly.

    • Author
      Mike Kanakos (Rank 3) 4 years ago

      Jamie,

      Sorry to hear you’re having an issue. Glad you found a workaround but I am curious to see if you could post your original error. I’d like to know to see if it is something I need to correct in the code.

      • Jamie Cottrell 4 years ago

        Sure. So there where no errors with running the code as supplied. But I then went to test a restore of one of the GPO’s. When I ran the Restore-GPO cmdlet I got the following error:

        Restore-GPO -Name ‘TEST’ -Path ‘C:\temp\2019-01-21\TEST\’

        Restore-GPO : There were no GPO backups found at path “C:\temp\2019-01-21\TEST\”.
        Parameter name: Path
        At line:1 char:1
        + Restore-GPO -Name ‘TEST’ -Path ‘C:\temp\2019-01-21\TEST\’
        + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo : NotSpecified: (:) [Restore-GPO], ArgumentException
        + FullyQualifiedErrorId : System.ArgumentException,Microsoft.GroupPolicy.Commands.RestoreGpoCommand

        I also tried to to restore the GPO via the Group Policy Management MMC snapin and this came up with ‘No Backups found’ when pointing the backup location to the specified folder.

        I think this has to do with the manifest.xml file. If you do a single backup you will see that the folder with the GUID is created as well as a manifest.xml file. In your code above you are only renaming the GUID folder name, but not doing anything with the manifest.xml file. So as the script loops through each GPO the manifest.xml file gets overwritten each time.

        Based on the above it seems like the maifest.xml file is needed to process the restore. Thats why I’ve changed the loop. My version now creates the folder with the GPO name then just backs up the GPO into that folder. That keeps the organisation of having the GPO folder names and also keeps the manifest.xml and GUID folder in tact.

        After making the change to the loop I can now run the Restore-GPO cmdlet that was getting the error and sucessfully restore the GPO.

        • Author
          Mike Kanakos (Rank 3) 4 years ago

          Jamie,

          I don’t have a testlab at my disposal right now to generate the proper syntax. I’ll do a test restore tomorrow and follow up.

        • Author
          Mike Kanakos (Rank 3) 4 years ago

          Jamie,

          After reading your comment, I went back to the lab and tested the restore function. Yes, you were correct, restores were not working as expected. The reason was that I did not retain the BackupID.

          But I did a small re-write of the script and corrected the code so that restores will work as well as keeping the names of the GPOs added to the GPO backup folders. However, You will need my corresponding Restore-GroupPolicy script to make the restores work properly.

          The restore script was fully tested and is available right now in my Github Repo . Also, I will be writing a follow-up article that explains how to properly do a restore from the backups created by this script using the accompanying restore script.

          Lastly, I updated the article to reflect the changes in the code. Thank you for reaching out when you found a bug in my code!

  5. Mallikarjun 4 years ago

    I’m trying to execute the script but I’m getting the error..I have pasted the error  at the end of the script..

    Can you address this issue Please..Many thanks.

    My domain name :- ABC.com
    My server name :- DC1.ABC.com
    Path to save :- C:\Backups.

    Script :-

    [CmdletBinding(SupportsShouldProcess=$true)]
    param (
    [Parameter(Mandatory=$True,Position=0)]
    [string]
    $Path,

    [Parameter()]
    [string]
    $Domain = (Get-WmiObject Win32_ComputerSystem).Domain,

    [Parameter()]
    [string]
    $Server
    )

    begin {

    #Get current GPO information
    import-module GroupPolicy
    $GPOInfo = Get-GPO -All -Domain ABC.COM -Server DC1.ABC.COM

    #Create a date-based folder to save a backup of Group Policies to
    $Date = Get-Date -UFormat “2019-01-21”
    $UpdatedPath = “c:\backups\$date”

    New-item $UpdatedPath -ItemType directory | Out-Null

    Write-Host “Will back up GPOs to $UpdatedPath”
    } #End of begin block

    process {

    ForEach ($GPO in $GPOInfo) {

    #Assign temp variables for various parts of GPO data
    Write-Host “Backing up GPO named: ” $GPO.Displayname
    $BackupInfo = Backup-GPO -Name $GPO.DisplayName -Domain $Domain -path $UpdatedPath -Server $Server
    $GpoBackupID = $BackupInfo.ID.Guid
    $GpoGuid = $BackupInfo.GPOID.Guid
    $GpoName = $BackupInfo.DisplayName
    $CurrentFolderName = $UpdatedPath + “\” + “{“+ $GpoBackupID + “}”
    $NewFolderName = $UpdatedPath + “\” + $GPOName

    #Rename the newly created GPO backup subfolder from its GPO ID to the GPO Displayname
    rename-item $CurrentFolderName -newname $NewFolderName

    } #End ForEach loop

    } #End of process block

    Error message :-

    Will back up GPOs to c:\backups\2019-01-21
    Backing up GPO named:  GPO3
    Backup-GPO : Cannot validate argument on parameter ‘Server’. The argument is null or empty. Supply an argument that
    is not null or empty and then try the command again.
    At line:37 char:103
    +             $BackupInfo = Backup-GPO -Name $GPO.DisplayName -Domain $Domain -path $UpdatedPath -Server <<<<  $Serv
    er
    + CategoryInfo          : InvalidData: (:) [Backup-GPO], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.GroupPolicy.Commands.BackupGpoCommand

    Rename-Item : Cannot rename because item at ‘c:\backups\2019-01-21\{}’ does not exist.
    At line:45 char:24
    +             rename-item <<<<  $CurrentFolderName -newname $NewFolderName
    + CategoryInfo          : InvalidOperation: (:) [Rename-Item], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand

    Backing up GPO named:  GPO2
    Backup-GPO : Cannot validate argument on parameter ‘Server’. The argument is null or empty. Supply an argument that
    is not null or empty and then try the command again.
    At line:37 char:103
    +             $BackupInfo = Backup-GPO -Name $GPO.DisplayName -Domain $Domain -path $UpdatedPath -Server <<<<  $Serv
    er
    + CategoryInfo          : InvalidData: (:) [Backup-GPO], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.GroupPolicy.Commands.BackupGpoCommand

    Rename-Item : Cannot rename because item at ‘c:\backups\2019-01-21\{}’ does not exist.
    At line:45 char:24
    +             rename-item <<<<  $CurrentFolderName -newname $NewFolderName
    + CategoryInfo          : InvalidOperation: (:) [Rename-Item], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand

    Backing up GPO named:  Default Domain Policy
    Backup-GPO : Cannot validate argument on parameter ‘Server’. The argument is null or empty. Supply an argument that
    is not null or empty and then try the command again.
    At line:37 char:103
    +             $BackupInfo = Backup-GPO -Name $GPO.DisplayName -Domain $Domain -path $UpdatedPath -Server <<<<  $Serv
    er
    + CategoryInfo          : InvalidData: (:) [Backup-GPO], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.GroupPolicy.Commands.BackupGpoCommand

    Rename-Item : Cannot rename because item at ‘c:\backups\2019-01-21\{}’ does not exist.
    At line:45 char:24
    +             rename-item <<<<  $CurrentFolderName -newname $NewFolderName
    + CategoryInfo          : InvalidOperation: (:) [Rename-Item], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand

    Backing up GPO named:  GPO1
    Backup-GPO : Cannot validate argument on parameter ‘Server’. The argument is null or empty. Supply an argument that
    is not null or empty and then try the command again.
    At line:37 char:103
    +             $BackupInfo = Backup-GPO -Name $GPO.DisplayName -Domain $Domain -path $UpdatedPath -Server <<<<  $Serv
    er
    + CategoryInfo          : InvalidData: (:) [Backup-GPO], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.GroupPolicy.Commands.BackupGpoCommand

    Rename-Item : Cannot rename because item at ‘c:\backups\2019-01-21\{}’ does not exist.
    At line:45 char:24
    +             rename-item <<<<  $CurrentFolderName -newname $NewFolderName
    + CategoryInfo          : InvalidOperation: (:) [Rename-Item], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand

    Backing up GPO named:  Default Domain Controllers Policy
    Backup-GPO : Cannot validate argument on parameter ‘Server’. The argument is null or empty. Supply an argument that
    is not null or empty and then try the command again.
    At line:37 char:103
    +             $BackupInfo = Backup-GPO -Name $GPO.DisplayName -Domain $Domain -path $UpdatedPath -Server <<<<  $Serv
    er
    + CategoryInfo          : InvalidData: (:) [Backup-GPO], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.GroupPolicy.Commands.BackupGpoCommand

    Rename-Item : Cannot rename because item at ‘c:\backups\2019-01-21\{}’ does not exist.
    At line:45 char:24
    +             rename-item <<<<  $CurrentFolderName -newname $NewFolderName
    + CategoryInfo          : InvalidOperation: (:) [Rename-Item], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand
    _________________________________________________________________________________________________________________

    _________________________________________________________________________________________________________________

     

    • Author
      Mike Kanakos (Rank 3) 4 years ago

      It looks to be hanging on the Server parameter. However, I have re-written this script to fix a bug in the code. Please download a new copy of the code from the article or grab a copy from here.

       

      avatar
  6. Mallikarjun 4 years ago

    Hi Mike,

    I’m looking for taking the GPO has backup with Group policy object name..

    You wrote the 1st script and that’s for taking the GPO for the backup..

    I have used the same script and getting the error as mentioned above.. Can you address this issue.

    Regards,
    Mallikarjun.

    • Author
      Mike Kanakos (Rank 3) 4 years ago

      Mallikarjun,

      I have tested this script extensively and I can confirm it works, so I suspect it is something with the way that you are entering the syntax. Please show the syntax you typed exactly as entered. for example, I would like to see something like this (according to what you wrote):

      Backup-GroupPolicy -Path C:\Backups -Server DC1.ABC.com

  7. Mallikarjun 4 years ago

    Hi Mike Kanakos ,

    thanks for your response.. Please see the script mentioned below and let me know what modification required to execute this script without error.. This script will take backup of all the group policy object.

    CmdletBinding(SupportsShouldProcess=$true)]

    param (

    [Parameter(Mandatory=$True,Position=0)]

    [string]

    $Path,

    [Parameter()]

    [string]

    $Domain = (Get-WmiObject Win32_ComputerSystem).Domain,

    [Parameter()]

    [string]

    $Server

    )

    begin {

    #Get current GPO information

    $GPOInfo = Get-GPO -All -Domain tenet.adlab.test -Server USW04DC420.tenet.adlab.test

    #Create a date-based folder to save a backup of Group Policies to

    $Date = Get-Date -UFormat “2019-01-22”

    $UpdatedPath = “E:\GPbackups\$date”

    New-item $UpdatedPath -ItemType directory | Out-Null

    Write-Host “Will back up GPOs to $UpdatedPath”

    } #End of begin block

    process {

    ForEach ($GPO in $GPOInfo) {

    #Assign temp variables for various parts of GPO data

    Write-Host “Backing up GPO named: ” $GPO.Displayname

    $BackupInfo = Backup-GPO -Name $GPO.DisplayName -Domain $Domain -path $UpdatedPath -Server $Server

    $GpoBackupID = $BackupInfo.ID.Guid

    $GpoGuid = $BackupInfo.GPOID.Guid

    $GpoName = $BackupInfo.DisplayName

    $CurrentFolderName = $UpdatedPath + “\” + “{“+ $GpoBackupID + “}”

    $NewFolderName = $UpdatedPath + “\” + $GPOName

    #Rename the newly created GPO backup subfolder from its GPO ID to the GPO Displayname

    rename-item $CurrentFolderName -newname $NewFolderName

    } #End ForEach loop

    } #End of process block

    Regards,
    Mallikarjun.

     

  8. Karel 4 years ago

    Hi Mike,

    Your script looks super promising.

    I’m just not clear on where I should define the parameters.

    Maybe you could make it a little more dummy proof and point out exactly where in the script the parameters should be defined. It would really help me if you told me on which line # I should put the domain, server, and destination path.
    Sorry for asking stupid questions.

    Great work btw!

    KR,

    Kim

  9. Author
    Mike Kanakos (Rank 3) 4 years ago

    Hi Kim,

    I just want to make sure you and I are on the same page. This is not a flat script but a function. To run the function you need to load it into memory and then you can define parameters when you call the function.

    After loading the fucntion, you can see the parameters by running:
    Get Help Backup-GPO

    There are three parameters that you can use: Path, Domain and Server. The help file explains all these parameters in detail (lines 15 – 44).

    After loading the function, you simply add the parameters when you type the function name, like so:

    Backup-GroupPolicy -Path C:\Backups -Server DC1.ABC.com

    Also, please be aware that you will need my corresponding Restore-GroupPolicy script to make the restores work properly.

  10. Hi Mike,

    Any chance you have a process on using this function in a scheduled task?

    • Hi Mike,

      Sorry for the late reply back on this and hopefully you didn't get annoyed at my stupidly put together question. So what I meant to ask was are you going to put together an article on getting this function to work in a scheduled task? I figured it all out on my own on Server 2008 and 2016. The method that works in 2008 works on 2008 and 2016. However the method I got to work does not work on 2008. Would it be ok to post my directions on how to do it and reference this article?

      Sincerely,

      Will

  11. Tom 4 years ago

    Hi!

    I had to modify your script to get working on my domain,

    GPO names can have invalid characters that the filesystem can't use, so I had to insert the line

    $SafeGpoName = $GpoName.Split([IO.Path]::GetInvalidFileNameChars()) -join '_'

    To allow for the names to be saved, albeit modified.

    Thanks

     

     

  12. Basavaraj R Navalgund 4 years ago

    Hi Mike,

    Thank you for this script.

    It  is one which saves lots of time in manipulating the name of the GPO versus GPO ID.

    Regards

    Raj

     

  13. Brent 4 years ago

    Any suggestions on using your restore script to restore the backups to another domain?

    • Author
      Mike Kanakos (Rank 3) 4 years ago

      Hi Brent,

       

      Looking at my restore script. I realize I never created a parameter for a domain. Adding that parameter should do the trick because domain is a parameter on the original command. However, I have to say that I have never tested that scenario.

      I'll post a new version of the script in my GitHub repo. 

  14. jerry 4 years ago

    Dear Mike

    Im trying to create a script to reset windows 10 workstations to the default GPO. Would you have any examples ? I would be pushing it out thru Intune.

    Any advise would be appreciated.

  15. Jerry Gomez 4 years ago

    Hello Mike

    I wanted to know if you had seen any scripting for resetting's Group Policy for windows 10 OS. We are looking to reset to factory status. We would push out thru Azure / Intune.  If you have any ideas, please let me know. Thanks in advance.

    J

  16. Author
    Mike Kanakos (Rank 3) 4 years ago

    Hi Jerry,

    There is a way to do what you are asking. There are a few things to consider. Let me detail them for you.

    It sounds like you want to reset everything specifically on a Win 10 machine. Is that machine part of a domain? If so, then you need to stop applying domain group policies first. After that, you can reset the local group back to the defaults. See this link for details. 

    However, you probably had things changed according to domain GPO's that have tattooed the registry and need to be specifically reversed for them to be removed. You would need to do a careful eval of the domain GPO's FIRST and make sure you understand what is being changed and how it is applied. If you are confident that those changes can reversed, then you can follow the link I gave you. 

    But if the PC is domain joined, you can't reset local group policy because the domain GPO's will just come back down. It sounds like you want to move your policies to InTune instead of native AD. Keep in mind, about egress traffic. You might get a costly bill for deploying from Azure. 

    Another useful doc for this topic is here: Link

    Hope that helps!

    ​​​​​​​

    avatar
  17. jerry gomez (Rank 1) 4 years ago

    Hello Mike

    Thanks for the response. We initially pushed out thru Intune some GPO's. Now we just want to reset to Windows 10 factory settings. I put together some code below? Do you think I can execute to reset all back to default, without a reboot? Afterwards we will request employee to reboot.

    What do you think?

    Jerry

       #  Clear GPO Config   #
       #     by Jerry             #
      #    Last Updated     #
     #     09-18-2019      #
    #######################

    if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
        if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
            $CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArgument
            Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
        Exit
        }
    }

    RD /S /Q "%WinDir%\System32\GroupPolicyUsers"
    RD /S /Q "%WinDir%\System32\GroupPolicy"

    • Author
      Mike Kanakos (Rank 3) 4 years ago

      Jerry,

       

      I understand what you're trying to do but i can't get behind that plan. Why?

      Reversing group policies settings is more than just resetting the policies. Some settings are set via registry keys and those settings are not reversed automatically. if you set a value to 1 with a reg key, then only way to flip that back is to set the key to 0. That usually means you need another group policy to set the new value or update the old GPO to set the value to 0. 

      For that reason, i think you might not be super successful just resetting the policies back to the defaults.

       

  18. Joseph 4 years ago

    Hi this may seem silly, but I cannot see where to exactly add my path data or server if that is needed.

     

    I saved the newest script from github, made a new drive E:\ with 40 GB of data.

    The server this is running on is a DC so I want to backup the GPOs from it to this directory "E:\GPObackups\backups"

    I'm not sure if the server can be blank or can be localhost but assuming the name is DC02 and that path above what changes or where exactly do I put these settings in the Backup-GroupPolicy.ps1 in order to get this to work and backup to that folder?

    Once it works once I will schedule a task for each night.

     

     

     

    Getting errors like this currently:

     

    PS E:\GPObackups> E:\GPObackups\Backup-GroupPolicy.ps1
    At E:\GPObackups\Backup-GroupPolicy.ps1:11 char:25
    +     ——————–
    +                         ~
    Missing expression after unary operator '–'.
    At E:\GPObackups\Backup-GroupPolicy.ps1:12 char:5
    +     CGPBackup2018-12-21Default Domain Policy
    +     ~~~~~~~~~~~~~~~~~~~~~~~~~~
    Unexpected token 'CGPBackup2018-12-21Default' in expression or statement.
    At E:\GPObackups\Backup-GroupPolicy.ps1:58 char:1
    + [CmdletBinding(SupportsShouldProcess=$true)]
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Unexpected attribute 'CmdletBinding'.
    At E:\GPObackups\Backup-GroupPolicy.ps1:59 char:1
    + param (
    + ~~~~~
    Unexpected token 'param' in expression or statement.
    At E:\GPObackups\Backup-GroupPolicy.ps1:61 char:13
    +     [string]
    +             ~
    Missing closing ')' in expression.
    At E:\GPObackups\Backup-GroupPolicy.ps1:64 char:16
    +     [Parameter()]
    +                ~
    An expression was expected after '('.
    At E:\GPObackups\Backup-GroupPolicy.ps1:1 char:29
    + function Backup-GroupPolicy {
    +                             ~
    Missing closing '}' in statement block or type definition.
    At E:\GPObackups\Backup-GroupPolicy.ps1:71 char:5
    +     )
    +     ~
    Unexpected token ')' in expression or statement.
    At E:\GPObackups\Backup-GroupPolicy.ps1:81 char:29
    +         $UpdatedPath = $path$date
    +                             ~~~~~
    Unexpected token '$date' in expression or statement.
    At E:\GPObackups\Backup-GroupPolicy.ps1:110 char:5
    +     } #end of process block
    +     ~
    Unexpected token '}' in expression or statement.
    Not all parse errors were reported.  Correct the reported errors and try again.
        + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
        + FullyQualifiedErrorId : MissingExpressionAfterOperator
     

    • Author
      Mike Kanakos (Rank 3) 4 years ago

      Joseph,

      Sorry for the slow follow-up. Your issue is that you're running my code as if it were a flat script. It's not, it's a function, which means you need to load it into memory before you can run it correctly. I do this because its something i intended to run regularly and functions are more flexible than flat scripts.  

      to load a function, you need to DOT SOURCE it like so. 
       

      . \(PATH to PS1 file)\Backup-GroupPolicy.ps1

      Also, you can add the file to your profile and load it that way. You can then run the cmdlet at the cmd prompt and use the built-in help to see how to enter parameters after it has been loaded into memory. 

      The syntax you are looking for is as follows:
       

      Backup-GroupPolicy -path C:\Backup -Domain nwtraders.local -Server DC01

       

       

  19. Grim 3 years ago

    Hi Mike,

    Great script but unforuntately I've run into an issue. The company I work for has a specific name format for their GP's that I can't change. An example of a policy name here would be:

    | Test | Policy Name

    Running the script gives the following error due to | being an illegal character.

    rename-item : Illegal characters in path.
    At C:\Backups\Backup-GroupPolicy.ps1:105 char:13
    +             rename-item $CurrentFolderName -newname $NewFolderName
    +             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [Rename-Item], ArgumentException
        + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.RenameItemCommand

    The exported backups are then in folders just using the GUID.

  20. Eric 3 years ago

    Hi,

    Thanks for your script.

    I noticed a problem with the github version :

    This line doesn't test the path correctly :
    If (-Not $UpdatedPath) { New-item $UpdatedPath -ItemType directory | Out-Null }

    Should be something like :
    If (!(Test-Path $UpdatedPath)) { New-item $UpdatedPath -ItemType directory | Out-Null }

    Or maybe it works with Powershell without Test-Path with version > 6 ?

    For those wondering how to use the function :

    You can remove the first line and last line to turn it into a script.
    Or
    You can source it and then use it : > . .\script.ps1
    Or
    You can import it : > Import-module .\script.ps1 -Force

    Cheers

  21. Sus 3 years ago

    It helped me a lot!

  22. SysAD 3 months ago

    I am trying to use this script, but it’s just doing “nothing” when I run it.

    PS C:\Scripts> .\Backup-GroupPolicy -Path “C:\Scripts\GPO_BUs” -Server DC
    PS C:\Scripts>

    Any insight on this?

    • Author
      Mike Kanakos (Rank 3) 3 months ago

      The code i wrote is a function which means you have to load it into memory first or add it to your profile so it is autoloaded when you start your powershell prompt.

      to load the function:

      . (path to file)\backup-grouppolicy.ps1
      Notice the extra dot in the front of the line. You can also lookup dot-sourcing for a full explainer.

      then the cmdlet Backup-GroupPolicy will be avilable to use like any other cmdlet.

Leave a reply

Your email address will not be published.

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account