#Requires -version 2.0 # ----------------------------------------------------------------------------- # Script: Get-GPOBackup.ps1 # Version: 1.4 # Author: Jeffery Hicks # http://jdhitsolutions.com/blog # http://twitter.com/JeffHicks # Date: 5/23/2011 # Keywords: GPO, Backup, GroupPolicy, GUID, XML # Comments: # # "Those who forget to script are doomed to repeat their work." # # **************************************************************** # * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED * # * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF * # * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, * # * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. * # **************************************************************** # ----------------------------------------------------------------------------- Function Get-GPOBackup { <# .SYNOPSIS Retrieve GPO Backup information .DESCRIPTION This command will search a given path for Group Policy Object backups and write backup information to the pipeline. The command will write a custom object to the pipeline for each GPO backup like this. Backup : 5/2/2011 8:10:13 PM Name : WinRM Configuration BackupID : 5AAFD6DF-24C0-40EF-9DF1-AC9C279E010B Path : \\server01\backup\gpo\ Domain : jdhlab.local Guid : 38228a9f-f2ec-4b48-8829-4f3131e4f77c Comment : second backup If you want to only retrieve the most current backup version use the -Latest parameter. .PARAMETER Path The top leve folder to search. This can be a drive letter or a UNC. The parameter will default to the global $GPBackupPath variable. .PARAMETER Name The name of a GPO. Wildcards are permitted. .PARAMETER Latest If there are multiple backups of the same GPO, return the most recent version. .EXAMPLE PS C:\> Get-GPOBackup Returns GPO backup information from the default location stored in the global $GPBackupPath variable. .EXAMPLE PS C:\> Get-GPOBackup \\server01\backup\gpo -latest Return the most recent backup for each GPO. .EXAMPLE PS C:\> Get-GPOBackup \\coredc01\backup\gpo -name "Ex*Laptop" -latest | foreach {Import-GPO -TargetGuid $_.Guid -backupid $_.backupID -path $_.path} DisplayName : Executive Laptop DomainName : jdhlab.local Owner : JDHLAB\Domain Admins Id : af6f4a88-5e8a-49ce-84f7-f04677a7d80d GpoStatus : AllSettingsEnabled Description : configure C-level laptops CreationTime : 9/8/2010 8:36:10 AM ModificationTime : 5/23/2011 9:52:43 AM UserVersion : AD Version: 2, SysVol Version: 2 ComputerVersion : AD Version: 9, SysVol Version: 9 WmiFilter : Get the lastest version of the Executive Laptop GPO and import it back into Active Directory. .NOTES NAME : Get-GPOBackup VERSION : 1.4 LAST UPDATED: 5/24/2011 AUTHOR : Jeffery Hicks .LINK Get-GPO Backup-GPO .LINK http://jdhitsolutions.com/blog/2011/05/get-gpo-backup/ .INPUTS None .OUTPUTS Custom Object #> [cmdletbinding()] Param( [Parameter(Position=0,Mandatory=$False,HelpMessage="What is the path to the GPO backup folder?")] [ValidateNotNullOrEmpty()] [string]$Path=$global:GPBackupPath, [Parameter(Position=1)] [string]$Name, [switch]$Latest ) #validate $Path if (-Not $Path) { $Path=Read-Host "What is the path to the GPO backup folder?" } Try { Write-Verbose "Validating $Path" if (-Not (Test-Path $Path)) { Throw } } Catch { Write-Warning "Failed to find $Path" Break } #get each folder that looks like a GUID [regex]$regex="^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$" Write-Verbose "Enumerating folders under $Path" #define an array to hold each backup object $Backups=@() #find all folders named with a GUID Get-ChildItem -Path $path | Where {$_.name -Match $regex -AND $_.PSIsContainer} | foreach { #import the Bkupinfo.xml file $file=Join-Path $_.FullName -ChildPath "bkUpinfo.xml" Write-Verbose "Importing $file" [xml]$data=Get-Content -Path $file #parse the xml file for data $GPO=$data.BackupInst.GPODisplayName."#cdata-section" $GPOGuid=$data.BackupInst.GPOGuid."#cdata-section" $ID=$data.BackupInst.ID."#cdata-section" $Comment=$data.BackupInst.comment."#cdata-section" #convert backup time to a date time object [datetime]$Backup=$data.BackupInst.BackupTime."#cdata-section" $Domain=$data.BackupInst.GPODomain."#cdata-section" #write a custom object to the pipeline and add to the temporary array $Backups+=New-Object -TypeName PSObject -Property @{ Name=$GPO Comment=$Comment #strip off the {} from the Backup ID GUID BackupID=$ID.Replace("{","").Replace("}","") #strip off the {} from the GPO GUID Guid=$GPOGuid.Replace("{","").Replace("}","") Backup=$Backup Domain=$Domain Path=$Path } } #foreach #if searching by GPO name, then filter and get just those GPOs if ($Name) { Write-Verbose "Filtering for GPO: $Name" $Backups=$Backups | where {$_.Name -like $Name} } Write-Verbose "Found $($Backups.Count) GPO Backups" #if -Latest then only write out the most current version of each GPO if ($Latest) { Write-Verbose "Getting Latest Backups" $grouped=$Backups | Sort-Object -Property GUID | Group-Object -Property GUID $grouped | Foreach { $_.Group | Sort-Object -Property Backup | Select-Object -Last 1 } } else { $Backups } Write-Verbose "Ending function" } #end function