- Export and import to and from Excel with the PowerShell module ImportExcel - Thu, Apr 21 2022
- Getting started with the PSReadLine module for PowerShell - Thu, Feb 24 2022
- SecretsManagement module for PowerShell: Save passwords in PowerShell - Tue, Dec 22 2020
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
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.
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
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.
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!
I see on line 91, the hyphen is missing from path. It should be -path.
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.
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
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!
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.
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.
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.
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.
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.
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!
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
_________________________________________________________________________________________________________________
_________________________________________________________________________________________________________________
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.
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.
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):
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.
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
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.
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
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
To allow for the names to be saved, albeit modified.
Thanks
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
Thanks Raj,
Just don't forget to use the corresponding restore-GPO script. You can find also on 4sysops here:
https://4sysops.com/archives/restore-group-policy-with-powershell/
Any suggestions on using your restore script to restore the backups to another domain?
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.
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.
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
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!
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"
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.
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
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.
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:
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.
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
It helped me a lot!
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?
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.