Solved

PowerShell output file

Posted on 2014-02-14
12
599 Views
Last Modified: 2014-03-03
Hi Guys,
The below script works and outputs fine perfectly fine:
##########################################################################################################
<#
.SYNOPSIS
    Backs up all GPOs from a specified domain and includes additional GPO information.

.DESCRIPTION
    The script backs up all GPOs in a target domain and captures additional GPO management information, such
    as Scope of Management, Block Inheritance, Link Enabled, Link Order, Link Enforced and WMI Filters.

    The backup can then be used by a partner script to mirror GPOs in a test domain.

    Details:
    * Creates a XML file containing PSCustomObjects used by partner import script
    * Creates a XML file WMI filter details used by partner import script
    * Creates a CSV file of additional information for readability
    * Additional backup information includes SOM (Scope of Management) Path, Block Inheritance, Link Enabled,
      Link Order', Link Enforced and WMI Filter data
    * Each CSV SOM entry is made up of "DistinguishedName:BlockInheritance:LinkEnabled:LinkOrder:LinkEnforced"
    * Option to create a Migration Table (to then be manually updated)

    Requirements: 
    * PowerShell GroupPolicy Module
    * PowerShell ActiveDirectory Module
    * Group Policy Management Console

.EXAMPLE
   .\BackUp_GPOs.ps1 -Domain wintiptoys.com -BackupFolder "\\wingdc01\backups\"

   This will backup all GPOs in the domain wingtiptoys.com and store them in a date and time stamped folder 
   under \\wingdc01\backups\.

.EXAMPLE
   .\BackUp_GPOs.ps1 -Domain contoso.com -BackupFolder "c:\backups" -MigTable

   This will backup all GPOs in the domain contoso.com and store them in a date and time stamped folder 
   under c:\backups\. A migration table, MigrationTable.migtable, will also be created for manual editing.

.OUTPUTS
   Backup folder name in the format Year_Month_Day_HourMinuteSecond
   GpoDetails.xml
   WmiFilters.xml
   GpoInformation.csv
   MigrationTable.migtable (optional)

   EXIT CODES: 1 - GPMC not found

.NOTES
    THIS CODE-SAMPLE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR 
    FITNESS FOR A PARTICULAR PURPOSE.

    This sample is not supported under any Microsoft standard support program or service. 
    The script is provided AS IS without warranty of any kind. Microsoft further disclaims all
    implied warranties including, without limitation, any implied warranties of merchantability
    or of fitness for a particular purpose. The entire risk arising out of the use or performance
    of the sample and documentation remains with you. In no event shall Microsoft, its authors,
    or anyone else involved in the creation, production, or delivery of the script be liable for 
    any damages whatsoever (including, without limitation, damages for loss of business profits, 
    business interruption, loss of business information, or other pecuniary loss) arising out of 
    the use of or inability to use the sample or documentation, even if Microsoft has been advised 
    of the possibility of such damages, rising out of the use of or inability to use the sample script, 
    even if Microsoft has been advised of the possibility of such damages. 

#>
##########################################################################################################

#################################
## Script Options and Parameters
#################################

#Requires -version 3
#Requires -modules ActiveDirectory,GroupPolicy


#Define and validate parameters
[CmdletBinding()]
Param(
      #The target domain
      [parameter(Mandatory=$True,Position=1)]
      [ValidateScript({Get-ADDomain $_})] 
      [String]$Domain,

      #The backup folder
      [parameter(Mandatory=$True,Position=2)]
      [ValidateScript({Test-Path $_})]
      [String]$BackupFolder,

      #Whether to create a migration table
      [Switch] 
      $MigTable
      )


#Set strict mode to identify typographical errors (uncomment whilst editing script)
#Set-StrictMode -version Latest


##########################################################################################################

########
## Main
########

########################
##BACKUP FOLDER DETAILS
#Create a variable to represent a new backup folder
#(constructing the report name from date details and the supplied backup folder)
$Date = Get-Date

$SubBackupFolder = "$BackupFolder\" + `
                   "$($Date.Year)_" + `
                   "$("{0:D2}" -f $Date.Month)_" + `
                   "$("{0:D2}" -f $Date.Day)_" + `
                   "$("{0:D2}" -f $Date.Hour)" + `
                   "$("{0:D2}" -f $Date.Minute)" + `
                   "$("{0:D2}" -f $Date.Second)"


##################
##BACKUP ALL GPOs
#Create the backup folder
New-Item -ItemType Directory -Path $SubBackupFolder | Out-Null


#Make sure the backup folder has been created
If (Test-Path -Path $SubBackupFolder) {

    #Connect to the supplied domain
    $TargetDomain = Get-ADDomain $Domain
    

    #Obtain the domain FQDN
    $DomainFQDN = $TargetDomain.DNSRoot


    #Obtain the domain DN
    $DomainDN = $TargetDomain.DistinguishedName
    

    #Backup all the GPOs found in the domain
    $Backups = Backup-GPO -All -Path $SubBackupFolder -Domain $DomainFQDN -Comment "Scripted backup created by $env:userdomain\$env:username on $(Get-Date -format d)"


        #Instantiate an object for Group Policy Management (GPMC required)
        Try {

            $GPM = New-Object -ComObject GPMgmt.GPM
    
        }   #End of Try...
    
        Catch {

            #Display exit message to console
            $Message = "ERROR: Unable to connect to GPMC. Please check that it is installed."
            Write-Host
            Write-Error $Message
  
            #Exit the script
            Exit 1
    
        }   #End of Catch...


    #Import the GPM API constants
    $Constants = $GPM.getConstants()


    #Connect to the supplied domain
    $GpmDomain = $GPM.GetDomain($DomainFQDN,$Null,$Constants.UseAnyDc)



    ###################################
    ##COLLECT SPECIFIC GPO INFORMATION
    #Loop through each backed-up GPO
    ForEach ($Backup in $Backups) {

        #Get the GPO GUID for our target GPO
        $GpoGuid = $Backup.GpoId


        #Get the backup GUID for our target GPO
        $BackupGuid = $Backup.Id
        

        #Instantiate an object for the relevant GPO using GPM
        $GPO = $GpmDomain.GetGPO("{$GpoGuid}")


        #Get the GPO DisplayName property
        $GpoName = $GPO.DisplayName

            
            ##Retrieve SOM Information
            #Create a GPM search criteria object
            $GpmSearchCriteria = $GPM.CreateSearchCriteria()


            #Configure search critera for SOM links against a GPO
            $GpmSearchCriteria.Add($Constants.SearchPropertySOMLinks,$Constants.SearchOpContains,$GPO)


            #Perform the search
            $SOMs = $GpmDomain.SearchSOMs($GpmSearchCriteria)

        
            #Empty the SomPath variable
            $SomInfo = $Null

        
                #Loop through any SOMs returned and write them to a variable
                ForEach ($SOM in $SOMs) {

                    #Capture the SOM Distinguished Name
                    $SomDN = $SOM.Path

                
                    #Capture Block Inheritance state
                    $SomInheritance = $SOM.GPOInheritanceBlocked

                
                    #Get GPO Link information for the SOM
                    $GpoLinks = (Get-GPInheritance -Target $SomDN).GpoLinks


                        #Loop through the GPO Link information and match info that relates to our current GPO
                        ForEach ($GpoLink in $GpoLinks) {

                            If ($GpoLink.DisplayName -eq $GpoName) {

                                #Capture the GPO link status
                                $LinkEnabled = $GpoLink.Enabled


                                #Capture the GPO precedence order
                                $LinkOrder = $GpoLink.Order


                                #Capture Enforced state
                                $LinkEnforced = $GpoLink.Enforced


                            }   #End of If ($GpoLink.DisplayName -eq $GpoName)


                        }   #End of ForEach ($GpoLink in $GpoLinks)


                #Append the SOM DN, link status, link order and Block Inheritance info to $SomInfo
                [Array]$SomInfo += "$SomDN`:$SomInheritance`:$LinkEnabled`:$LinkOrder`:$LinkEnforced"
            
            
                }   #End of ForEach ($SOM in $SOMs)...


        ##Obtain WMI Filter path using Get-GPO
        $WmiFilter = (Get-GPO -Guid $GpoGuid).WMiFilter.Path
        
        #Split the value down and use the ID portion of the array
        $WMiFilter = ($WmiFilter -split "`"")[1]


        #Add selected GPO properties to a custom GPO object
        $GpoInfo = [PSCustomObject]@{

                BackupGuid = $BackupGuid
                Name = $GpoName
                GpoGuid = $GpoGuid
                SOMs = $SomInfo
                DomainDN = $DomainDN
                WmiFilter = $WmiFilter
        
        }   #End of $Properties...

        
        #Add our new object to an array
        [Array]$TotalGPOs += $GpoInfo


    }   #End of ForEach ($Backup in $Backups)...



    #####################
    ##BACKUP WMI FILTERS
    #Connect to the Active Directory to get details of the WMI filters
    $WmiFilters = Get-ADObject -Filter 'objectClass -eq "msWMI-Som"' `
                               -Properties msWMI-Author, msWMI-ID, msWMI-Name, msWMI-Parm1, msWMI-Parm2 `
                               -ErrorAction SilentlyContinue



    ######################
    ##CREATE REPORT FILES
    ##XML reports
    #Create a variable for the XML file representing custom information about the backed up GPOs
    $CustomGpoXML = "$SubBackupFolder\GpoDetails.xml"

    #Export our array of custom GPO objects to XML so they can be easily re-imported as objects
    $TotalGPOs | Export-Clixml -Path $CustomGpoXML

    #If $WMIFilters contains objects write these to an XML file
    If ($WmiFilters) {

        #Create a variable for the XML file representing the WMI filters
        $WmiXML = "$SubBackupFolder\WmiFilters.xml"

        #Export our array of WMI filters to XML so they can be easily re-imported as objects
        $WmiFilters | Export-Clixml -Path $WmiXML

    }   #End of If ($WmiFilters)


    ##CSV report
    #Create a variable for the CSV file that will contain the SOM (Scope of Management) information for each backed-up GPO
    $SOMReportCSV = "$SubBackupFolder\GpoInformation.csv"


    #Now, let's create the CSV report 
    ForEach ($CustomGPO in $TotalGPOs) {
            
        #Start constructing the CSV file line entry for the current GPO
        $CSVLine = "`"$($CustomGPO.Name)`",`"{$($CustomGPO.GPOGuid)}`","


        #Expand the SOMs property of the current object
        $CustomSOMs = $CustomGPO.SOMs


            #Loop through any SOMs returned
            ForEach ($CustomSOM in $CustomSOMs) {

                #Append the SOM path to our CSV line
                $CSVLine += "`"$CustomSOM`","

         
           }   #End of ForEach ($CustomSOM in $CustomSOMs)...


       #Write the newly constructed CSV line to the report
       Add-Content -Path $SOMReportCSV -Value $CSVLine


    }   #End of ForEach ($CustomGPO in $TotalGPOs)...


    ###########
    ##MIGTABLE
    #Check whether a migration table should be created
    If ($MigTable) {

        #Create a variable for the migration table
        $MigrationFile = "$SubBackupFolder\MigrationTable.migtable"

        #Create a migration table 
        $MigrationTable = $GPM.CreateMigrationTable()


        #Connect to the backup directory
        $GpmBackupDir = $GPM.GetBackUpDir($SubBackupFolder)


        #Reset the GPM search criterea
        $GpmSearchCriteria = $GPM.CreateSearchCriteria()


        #Configure search critera for the most recent backup
        $GpmSearchCriteria.Add($Constants.SearchPropertyBackupMostRecent,$Constants.SearchOpEquals,$True)
   

        #Get GPO information
        $BackedUpGPOs = $GpmBackupDir.SearchBackups($GpmSearchCriteria)


            #Add the information to our migration table
            ForEach ($BackedUpGPO in $BackedUpGPOs) {

                $MigrationTable.Add($Constants.ProcessSecurity,$BackedUpGPO)
        
            }   #End of ForEach ($BackedUpGPO in $BackedUpGPOs)...


        #Save the migration table
        $MigrationTable.Save($MigrationFile)


    }   #End of If ($MigTable)...


}   #End of If (Test-Path $SubBackupFolder)...

Open in new window

But if I make the following changes to line 140-143 (to only grab GPO's that have "win7" in the name), the output file GpoDetails.xml is empty (null) and GpoInformation.csv doesnt get generated. Would anyone know why? Below is the minor change I have made (in bold).
##########################################################################################################
<#
.SYNOPSIS
    Backs up all GPOs from a specified domain and includes additional GPO information.

.DESCRIPTION
    The script backs up all GPOs in a target domain and captures additional GPO management information, such
    as Scope of Management, Block Inheritance, Link Enabled, Link Order, Link Enforced and WMI Filters.

    The backup can then be used by a partner script to mirror GPOs in a test domain.

    Details:
    * Creates a XML file containing PSCustomObjects used by partner import script
    * Creates a XML file WMI filter details used by partner import script
    * Creates a CSV file of additional information for readability
    * Additional backup information includes SOM (Scope of Management) Path, Block Inheritance, Link Enabled,
      Link Order', Link Enforced and WMI Filter data
    * Each CSV SOM entry is made up of "DistinguishedName:BlockInheritance:LinkEnabled:LinkOrder:LinkEnforced"
    * Option to create a Migration Table (to then be manually updated)

    Requirements: 
    * PowerShell GroupPolicy Module
    * PowerShell ActiveDirectory Module
    * Group Policy Management Console

.EXAMPLE
   .\BackUp_GPOs.ps1 -Domain wintiptoys.com -BackupFolder "\\wingdc01\backups\"

   This will backup all GPOs in the domain wingtiptoys.com and store them in a date and time stamped folder 
   under \\wingdc01\backups\.

.EXAMPLE
   .\BackUp_GPOs.ps1 -Domain contoso.com -BackupFolder "c:\backups" -MigTable

   This will backup all GPOs in the domain contoso.com and store them in a date and time stamped folder 
   under c:\backups\. A migration table, MigrationTable.migtable, will also be created for manual editing.

.OUTPUTS
   Backup folder name in the format Year_Month_Day_HourMinuteSecond
   GpoDetails.xml
   WmiFilters.xml
   GpoInformation.csv
   MigrationTable.migtable (optional)

   EXIT CODES: 1 - GPMC not found

.NOTES
    THIS CODE-SAMPLE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR 
    FITNESS FOR A PARTICULAR PURPOSE.

    This sample is not supported under any Microsoft standard support program or service. 
    The script is provided AS IS without warranty of any kind. Microsoft further disclaims all
    implied warranties including, without limitation, any implied warranties of merchantability
    or of fitness for a particular purpose. The entire risk arising out of the use or performance
    of the sample and documentation remains with you. In no event shall Microsoft, its authors,
    or anyone else involved in the creation, production, or delivery of the script be liable for 
    any damages whatsoever (including, without limitation, damages for loss of business profits, 
    business interruption, loss of business information, or other pecuniary loss) arising out of 
    the use of or inability to use the sample or documentation, even if Microsoft has been advised 
    of the possibility of such damages, rising out of the use of or inability to use the sample script, 
    even if Microsoft has been advised of the possibility of such damages. 

#>
##########################################################################################################

#################################
## Script Options and Parameters
#################################

#Requires -version 3
#Requires -modules ActiveDirectory,GroupPolicy


#Define and validate parameters
[CmdletBinding()]
Param(
      #The target domain
      [parameter(Mandatory=$True,Position=1)]
      [ValidateScript({Get-ADDomain $_})] 
      [String]$Domain,

      #The backup folder
      [parameter(Mandatory=$True,Position=2)]
      [ValidateScript({Test-Path $_})]
      [String]$BackupFolder,

      #Whether to create a migration table
      [Switch] 
      $MigTable
      )


#Set strict mode to identify typographical errors (uncomment whilst editing script)
#Set-StrictMode -version Latest


##########################################################################################################

########
## Main
########

########################
##BACKUP FOLDER DETAILS
#Create a variable to represent a new backup folder
#(constructing the report name from date details and the supplied backup folder)
$Date = Get-Date

$SubBackupFolder = "$BackupFolder\" + `
                   "$($Date.Year)_" + `
                   "$("{0:D2}" -f $Date.Month)_" + `
                   "$("{0:D2}" -f $Date.Day)_" + `
                   "$("{0:D2}" -f $Date.Hour)" + `
                   "$("{0:D2}" -f $Date.Minute)" + `
                   "$("{0:D2}" -f $Date.Second)"


##################
##BACKUP ALL GPOs
#Create the backup folder
New-Item -ItemType Directory -Path $SubBackupFolder | Out-Null


#Make sure the backup folder has been created
If (Test-Path -Path $SubBackupFolder) {

    #Connect to the supplied domain
    $TargetDomain = Get-ADDomain $Domain
    

    #Obtain the domain FQDN
    $DomainFQDN = $TargetDomain.DNSRoot


    #Obtain the domain DN
    $DomainDN = $TargetDomain.DistinguishedName
    

    #Backup all the GPOs found in the domain
$GPOs = Get-GPO -All | where {$_.DisplayName -like '*win7*'}
foreach ($GPO in $GPOs) {
    Backup-GPO -Name $GPO.DisplayName }


        #Instantiate an object for Group Policy Management (GPMC required)
        Try {

            $GPM = New-Object -ComObject GPMgmt.GPM
    
        }   #End of Try...
    
        Catch {

            #Display exit message to console
            $Message = "ERROR: Unable to connect to GPMC. Please check that it is installed."
            Write-Host
            Write-Error $Message
  
            #Exit the script
            Exit 1
    
        }   #End of Catch...


    #Import the GPM API constants
    $Constants = $GPM.getConstants()


    #Connect to the supplied domain
    $GpmDomain = $GPM.GetDomain($DomainFQDN,$Null,$Constants.UseAnyDc)



    ###################################
    ##COLLECT SPECIFIC GPO INFORMATION
    #Loop through each backed-up GPO
    ForEach ($Backup in $Backups) {

        #Get the GPO GUID for our target GPO
        $GpoGuid = $Backup.GpoId


        #Get the backup GUID for our target GPO
        $BackupGuid = $Backup.Id
        

        #Instantiate an object for the relevant GPO using GPM
        $GPO = $GpmDomain.GetGPO("{$GpoGuid}")


        #Get the GPO DisplayName property
        $GpoName = $GPO.DisplayName

            
            ##Retrieve SOM Information
            #Create a GPM search criteria object
            $GpmSearchCriteria = $GPM.CreateSearchCriteria()


            #Configure search critera for SOM links against a GPO
            $GpmSearchCriteria.Add($Constants.SearchPropertySOMLinks,$Constants.SearchOpContains,$GPO)


            #Perform the search
            $SOMs = $GpmDomain.SearchSOMs($GpmSearchCriteria)

        
            #Empty the SomPath variable
            $SomInfo = $Null

        
                #Loop through any SOMs returned and write them to a variable
                ForEach ($SOM in $SOMs) {

                    #Capture the SOM Distinguished Name
                    $SomDN = $SOM.Path

                
                    #Capture Block Inheritance state
                    $SomInheritance = $SOM.GPOInheritanceBlocked

                
                    #Get GPO Link information for the SOM
                    $GpoLinks = (Get-GPInheritance -Target $SomDN).GpoLinks


                        #Loop through the GPO Link information and match info that relates to our current GPO
                        ForEach ($GpoLink in $GpoLinks) {

                            If ($GpoLink.DisplayName -eq $GpoName) {

                                #Capture the GPO link status
                                $LinkEnabled = $GpoLink.Enabled


                                #Capture the GPO precedence order
                                $LinkOrder = $GpoLink.Order


                                #Capture Enforced state
                                $LinkEnforced = $GpoLink.Enforced


                            }   #End of If ($GpoLink.DisplayName -eq $GpoName)


                        }   #End of ForEach ($GpoLink in $GpoLinks)


                #Append the SOM DN, link status, link order and Block Inheritance info to $SomInfo
                [Array]$SomInfo += "$SomDN`:$SomInheritance`:$LinkEnabled`:$LinkOrder`:$LinkEnforced"
            
            
                }   #End of ForEach ($SOM in $SOMs)...


        ##Obtain WMI Filter path using Get-GPO
        $WmiFilter = (Get-GPO -Guid $GpoGuid).WMiFilter.Path
        
        #Split the value down and use the ID portion of the array
        $WMiFilter = ($WmiFilter -split "`"")[1]


        #Add selected GPO properties to a custom GPO object
        $GpoInfo = [PSCustomObject]@{

                BackupGuid = $BackupGuid
                Name = $GpoName
                GpoGuid = $GpoGuid
                SOMs = $SomInfo
                DomainDN = $DomainDN
                WmiFilter = $WmiFilter
        
        }   #End of $Properties...

        
        #Add our new object to an array
        [Array]$TotalGPOs += $GpoInfo


    }   #End of ForEach ($Backup in $Backups)...



    #####################
    ##BACKUP WMI FILTERS
    #Connect to the Active Directory to get details of the WMI filters
    $WmiFilters = Get-ADObject -Filter 'objectClass -eq "msWMI-Som"' `
                               -Properties msWMI-Author, msWMI-ID, msWMI-Name, msWMI-Parm1, msWMI-Parm2 `
                               -ErrorAction SilentlyContinue



    ######################
    ##CREATE REPORT FILES
    ##XML reports
    #Create a variable for the XML file representing custom information about the backed up GPOs
    $CustomGpoXML = "$SubBackupFolder\GpoDetails.xml"

    #Export our array of custom GPO objects to XML so they can be easily re-imported as objects
    $TotalGPOs | Export-Clixml -Path $CustomGpoXML

    #If $WMIFilters contains objects write these to an XML file
    If ($WmiFilters) {

        #Create a variable for the XML file representing the WMI filters
        $WmiXML = "$SubBackupFolder\WmiFilters.xml"

        #Export our array of WMI filters to XML so they can be easily re-imported as objects
        $WmiFilters | Export-Clixml -Path $WmiXML

    }   #End of If ($WmiFilters)


    ##CSV report
    #Create a variable for the CSV file that will contain the SOM (Scope of Management) information for each backed-up GPO
    $SOMReportCSV = "$SubBackupFolder\GpoInformation.csv"


    #Now, let's create the CSV report 
    ForEach ($CustomGPO in $TotalGPOs) {
            
        #Start constructing the CSV file line entry for the current GPO
        $CSVLine = "`"$($CustomGPO.Name)`",`"{$($CustomGPO.GPOGuid)}`","


        #Expand the SOMs property of the current object
        $CustomSOMs = $CustomGPO.SOMs


            #Loop through any SOMs returned
            ForEach ($CustomSOM in $CustomSOMs) {

                #Append the SOM path to our CSV line
                $CSVLine += "`"$CustomSOM`","

         
           }   #End of ForEach ($CustomSOM in $CustomSOMs)...


       #Write the newly constructed CSV line to the report
       Add-Content -Path $SOMReportCSV -Value $CSVLine


    }   #End of ForEach ($CustomGPO in $TotalGPOs)...


    ###########
    ##MIGTABLE
    #Check whether a migration table should be created
    If ($MigTable) {

        #Create a variable for the migration table
        $MigrationFile = "$SubBackupFolder\MigrationTable.migtable"

        #Create a migration table 
        $MigrationTable = $GPM.CreateMigrationTable()


        #Connect to the backup directory
        $GpmBackupDir = $GPM.GetBackUpDir($SubBackupFolder)


        #Reset the GPM search criterea
        $GpmSearchCriteria = $GPM.CreateSearchCriteria()


        #Configure search critera for the most recent backup
        $GpmSearchCriteria.Add($Constants.SearchPropertyBackupMostRecent,$Constants.SearchOpEquals,$True)
   

        #Get GPO information
        $BackedUpGPOs = $GpmBackupDir.SearchBackups($GpmSearchCriteria)


            #Add the information to our migration table
            ForEach ($BackedUpGPO in $BackedUpGPOs) {

                $MigrationTable.Add($Constants.ProcessSecurity,$BackedUpGPO)
        
            }   #End of ForEach ($BackedUpGPO in $BackedUpGPOs)...


        #Save the migration table
        $MigrationTable.Save($MigrationFile)


    }   #End of If ($MigTable)...


}   #End of If (Test-Path $SubBackupFolder)...

Open in new window

0
Comment
Question by:levertm
  • 6
  • 5
12 Comments
 
LVL 34

Expert Comment

by:Dan Craciun
ID: 39860382
You no longer put the result in the $Backups variable, so the following loop (ForEach ($Backup in $Backups) - line 178) never gets executed.

Maybe something like this:

foreach ($GPO in $GPOs) {
    $Backups += (Backup-GPO -Name $GPO.DisplayName) }

HTH,
Dan
0
 

Author Comment

by:levertm
ID: 39860392
Thank you Dan, I think I see what you mean. How would I rectify this problem keeping my modifications?
Edit: I'll try your suggestion right away in my lab.
0
 

Author Comment

by:levertm
ID: 39860418
I'm now getting an Unexpected token '}' in expression or statement error.

I basically added your modification and replaced with in line 177/178
0
 
LVL 34

Expert Comment

by:Dan Craciun
ID: 39860425
Why did you modify the lines 177/178???

The code I gave you was supposed to replace the lines 142/143
0
 

Author Comment

by:levertm
ID: 39860449
My bad, hitting my head on the wall all day on this.

I made the modifications to line 142/143, where it should of been as you suggested. Stil getting the same error.

##########################################################################################################
<#
.SYNOPSIS
    Backs up all GPOs from a specified domain and includes additional GPO information.

.DESCRIPTION
    The script backs up all GPOs in a target domain and captures additional GPO management information, such
    as Scope of Management, Block Inheritance, Link Enabled, Link Order, Link Enforced and WMI Filters.

    The backup can then be used by a partner script to mirror GPOs in a test domain.

    Details:
    * Creates a XML file containing PSCustomObjects used by partner import script
    * Creates a XML file WMI filter details used by partner import script
    * Creates a CSV file of additional information for readability
    * Additional backup information includes SOM (Scope of Management) Path, Block Inheritance, Link Enabled,
      Link Order', Link Enforced and WMI Filter data
    * Each CSV SOM entry is made up of "DistinguishedName:BlockInheritance:LinkEnabled:LinkOrder:LinkEnforced"
    * Option to create a Migration Table (to then be manually updated)

    Requirements: 
    * PowerShell GroupPolicy Module
    * PowerShell ActiveDirectory Module
    * Group Policy Management Console

.EXAMPLE
   .\BackUp_GPOs.ps1 -Domain wintiptoys.com -BackupFolder "\\wingdc01\backups\"

   This will backup all GPOs in the domain wingtiptoys.com and store them in a date and time stamped folder 
   under \\wingdc01\backups\.

.EXAMPLE
   .\BackUp_GPOs.ps1 -Domain contoso.com -BackupFolder "c:\backups" -MigTable

   This will backup all GPOs in the domain contoso.com and store them in a date and time stamped folder 
   under c:\backups\. A migration table, MigrationTable.migtable, will also be created for manual editing.

.OUTPUTS
   Backup folder name in the format Year_Month_Day_HourMinuteSecond
   GpoDetails.xml
   WmiFilters.xml
   GpoInformation.csv
   MigrationTable.migtable (optional)

   EXIT CODES: 1 - GPMC not found

.NOTES
    THIS CODE-SAMPLE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR 
    FITNESS FOR A PARTICULAR PURPOSE.

    This sample is not supported under any Microsoft standard support program or service. 
    The script is provided AS IS without warranty of any kind. Microsoft further disclaims all
    implied warranties including, without limitation, any implied warranties of merchantability
    or of fitness for a particular purpose. The entire risk arising out of the use or performance
    of the sample and documentation remains with you. In no event shall Microsoft, its authors,
    or anyone else involved in the creation, production, or delivery of the script be liable for 
    any damages whatsoever (including, without limitation, damages for loss of business profits, 
    business interruption, loss of business information, or other pecuniary loss) arising out of 
    the use of or inability to use the sample or documentation, even if Microsoft has been advised 
    of the possibility of such damages, rising out of the use of or inability to use the sample script, 
    even if Microsoft has been advised of the possibility of such damages. 

#>
##########################################################################################################

#################################
## Script Options and Parameters
#################################
#Requires -version 3
#Requires -modules ActiveDirectory,GroupPolicy


#Define and validate parameters
[CmdletBinding()]
Param(
      #The target domain
      [parameter(Mandatory=$True,Position=1)]
      [ValidateScript({Get-ADDomain $_})] 
      [String]$Domain,

      #The backup folder
      [parameter(Mandatory=$True,Position=2)]
      [ValidateScript({Test-Path $_})]
      [String]$BackupFolder,

      #Whether to create a migration table
      [Switch] 
      $MigTable
      )


#Set strict mode to identify typographical errors (uncomment whilst editing script)
#Set-StrictMode -version Latest


##########################################################################################################

########
## Main
########

########################
##BACKUP FOLDER DETAILS
#Create a variable to represent a new backup folder
#(constructing the report name from date details and the supplied backup folder)
$Date = Get-Date

$SubBackupFolder = "$BackupFolder\" + `
                   "$($Date.Year)_" + `
                   "$("{0:D2}" -f $Date.Month)_" + `
                   "$("{0:D2}" -f $Date.Day)_" + `
                   "$("{0:D2}" -f $Date.Hour)" + `
                   "$("{0:D2}" -f $Date.Minute)" + `
                   "$("{0:D2}" -f $Date.Second)"


##################
##BACKUP ALL GPOs
#Create the backup folder
New-Item -ItemType Directory -Path $SubBackupFolder | Out-Null


#Make sure the backup folder has been created
If (Test-Path -Path $SubBackupFolder) {

    #Connect to the supplied domain
    $TargetDomain = Get-ADDomain $Domain
    

    #Obtain the domain FQDN
    $DomainFQDN = $TargetDomain.DNSRoot


    #Obtain the domain DN
    $DomainDN = $TargetDomain.DistinguishedName
    

    #Backup all the GPOs found in the domain
	$GPOs = Get-GPO -All | Where {$_.DisplayName -like '*win9*'}
	foreach ($GPO in $GPOs) {
    $Backups += (Backup-GPO -Name $GPO.DisplayName) } -Path $SubBackupFolder -Domain $DomainFQDN -Comment "Test0r" }


        #Instantiate an object for Group Policy Management (GPMC required)
        Try {

            $GPM = New-Object -ComObject GPMgmt.GPM
    
        }   #End of Try...
    
        Catch {

            #Display exit message to console
            $Message = "ERROR: Unable to connect to GPMC. Please check that it is installed."
            Write-Host
            Write-Error $Message
  
            #Exit the script
            Exit 1
    
        }   #End of Catch...


    #Import the GPM API constants
    $Constants = $GPM.getConstants()


    #Connect to the supplied domain
    $GpmDomain = $GPM.GetDomain($DomainFQDN,$Null,$Constants.UseAnyDc)



    ###################################
    ##COLLECT SPECIFIC GPO INFORMATION
    #Loop through each backed-up GPO
    ForEach ($Backup in $Backups) {

        #Get the GPO GUID for our target GPO
        $GpoGuid = $Backup.GpoId


        #Get the backup GUID for our target GPO
        $BackupGuid = $Backup.Id
        

        #Instantiate an object for the relevant GPO using GPM
        $GPO = $GpmDomain.GetGPO("{$GpoGuid}")


        #Get the GPO DisplayName property
        $GpoName = $GPO.DisplayName

            
            ##Retrieve SOM Information
            #Create a GPM search criteria object
            $GpmSearchCriteria = $GPM.CreateSearchCriteria()


            #Configure search critera for SOM links against a GPO
            $GpmSearchCriteria.Add($Constants.SearchPropertySOMLinks,$Constants.SearchOpContains,$GPO)


            #Perform the search
            $SOMs = $GpmDomain.SearchSOMs($GpmSearchCriteria)

        
            #Empty the SomPath variable
            $SomInfo = $Null

        
                #Loop through any SOMs returned and write them to a variable
                ForEach ($SOM in $SOMs) {

                    #Capture the SOM Distinguished Name
                    $SomDN = $SOM.Path

                
                    #Capture Block Inheritance state
                    $SomInheritance = $SOM.GPOInheritanceBlocked

                
                    #Get GPO Link information for the SOM
                    $GpoLinks = (Get-GPInheritance -Target $SomDN).GpoLinks


                        #Loop through the GPO Link information and match info that relates to our current GPO
                        ForEach ($GpoLink in $GpoLinks) {

                            If ($GpoLink.DisplayName -eq $GpoName) {

                                #Capture the GPO link status
                                $LinkEnabled = $GpoLink.Enabled


                                #Capture the GPO precedence order
                                $LinkOrder = $GpoLink.Order


                                #Capture Enforced state
                                $LinkEnforced = $GpoLink.Enforced


                            }   #End of If ($GpoLink.DisplayName -eq $GpoName)


                        }   #End of ForEach ($GpoLink in $GpoLinks)


                #Append the SOM DN, link status, link order and Block Inheritance info to $SomInfo
                [Array]$SomInfo += "$SomDN`:$SomInheritance`:$LinkEnabled`:$LinkOrder`:$LinkEnforced"
            
            
                }   #End of ForEach ($SOM in $SOMs)...


        ##Obtain WMI Filter path using Get-GPO
        $WmiFilter = (Get-GPO -Guid $GpoGuid).WMiFilter.Path
        
        #Split the value down and use the ID portion of the array
        $WMiFilter = ($WmiFilter -split "`"")[1]


        #Add selected GPO properties to a custom GPO object
        $GpoInfo = [PSCustomObject]@{

                BackupGuid = $BackupGuid
                Name = $GpoName
                GpoGuid = $GpoGuid
                SOMs = $SomInfo
                DomainDN = $DomainDN
                WmiFilter = $WmiFilter
        
        }   #End of $Properties...

        
        #Add our new object to an array
        [Array]$TotalGPOs += $GpoInfo


    }   #End of ForEach ($Backup in $Backups)...



    #####################
    ##BACKUP WMI FILTERS
    #Connect to the Active Directory to get details of the WMI filters
    $WmiFilters = Get-ADObject -Filter 'objectClass -eq "msWMI-Som"' `
                               -Properties msWMI-Author, msWMI-ID, msWMI-Name, msWMI-Parm1, msWMI-Parm2 `
                               -ErrorAction SilentlyContinue



    ######################
    ##CREATE REPORT FILES
    ##XML reports
    #Create a variable for the XML file representing custom information about the backed up GPOs
    $CustomGpoXML = "$SubBackupFolder\GpoDetails.xml"

    #Export our array of custom GPO objects to XML so they can be easily re-imported as objects
    $TotalGPOs | Export-Clixml -Path $CustomGpoXML

    #If $WMIFilters contains objects write these to an XML file
    If ($WmiFilters) {

        #Create a variable for the XML file representing the WMI filters
        $WmiXML = "$SubBackupFolder\WmiFilters.xml"

        #Export our array of WMI filters to XML so they can be easily re-imported as objects
        $WmiFilters | Export-Clixml -Path $WmiXML

    }   #End of If ($WmiFilters)


    ##CSV report
    #Create a variable for the CSV file that will contain the SOM (Scope of Management) information for each backed-up GPO
    $SOMReportCSV = "$SubBackupFolder\GpoInformation.csv"


    #Now, let's create the CSV report 
    ForEach ($CustomGPO in $TotalGPOs) {
            
        #Start constructing the CSV file line entry for the current GPO
        $CSVLine = "`"$($CustomGPO.Name)`",`"{$($CustomGPO.GPOGuid)}`","


        #Expand the SOMs property of the current object
        $CustomSOMs = $CustomGPO.SOMs


            #Loop through any SOMs returned
            ForEach ($CustomSOM in $CustomSOMs) {

                #Append the SOM path to our CSV line
                $CSVLine += "`"$CustomSOM`","

         
           }   #End of ForEach ($CustomSOM in $CustomSOMs)...


       #Write the newly constructed CSV line to the report
       Add-Content -Path $SOMReportCSV -Value $CSVLine


    }   #End of ForEach ($CustomGPO in $TotalGPOs)...


    ###########
    ##MIGTABLE
    #Check whether a migration table should be created
    If ($MigTable) {

        #Create a variable for the migration table
        $MigrationFile = "$SubBackupFolder\MigrationTable.migtable"

        #Create a migration table 
        $MigrationTable = $GPM.CreateMigrationTable()


        #Connect to the backup directory
        $GpmBackupDir = $GPM.GetBackUpDir($SubBackupFolder)
        #Reset the GPM search criterea
        $GpmSearchCriteria = $GPM.CreateSearchCriteria()


        #Configure search critera for the most recent backup
        $GpmSearchCriteria.Add($Constants.SearchPropertyBackupMostRecent,$Constants.SearchOpEquals,$True)
   

        #Get GPO information
        $BackedUpGPOs = $GpmBackupDir.SearchBackups($GpmSearchCriteria)


            #Add the information to our migration table
            ForEach ($BackedUpGPO in $BackedUpGPOs) {

                $MigrationTable.Add($Constants.ProcessSecurity,$BackedUpGPO)
        
            }   #End of ForEach ($BackedUpGPO in $BackedUpGPOs)...


        #Save the migration table
        $MigrationTable.Save($MigrationFile)


    }   #End of If ($MigTable)...


}   #End of If (Test-Path $SubBackupFolder)...

Open in new window

0
 
LVL 34

Expert Comment

by:Dan Craciun
ID: 39860474
You added some additional code on line 142. I don't know from where.

Try this:

##########################################################################################################
<#
.SYNOPSIS
    Backs up all GPOs from a specified domain and includes additional GPO information.

.DESCRIPTION
    The script backs up all GPOs in a target domain and captures additional GPO management information, such
    as Scope of Management, Block Inheritance, Link Enabled, Link Order, Link Enforced and WMI Filters.

    The backup can then be used by a partner script to mirror GPOs in a test domain.

    Details:
    * Creates a XML file containing PSCustomObjects used by partner import script
    * Creates a XML file WMI filter details used by partner import script
    * Creates a CSV file of additional information for readability
    * Additional backup information includes SOM (Scope of Management) Path, Block Inheritance, Link Enabled,
      Link Order', Link Enforced and WMI Filter data
    * Each CSV SOM entry is made up of "DistinguishedName:BlockInheritance:LinkEnabled:LinkOrder:LinkEnforced"
    * Option to create a Migration Table (to then be manually updated)

    Requirements: 
    * PowerShell GroupPolicy Module
    * PowerShell ActiveDirectory Module
    * Group Policy Management Console

.EXAMPLE
   .\BackUp_GPOs.ps1 -Domain wintiptoys.com -BackupFolder "\\wingdc01\backups\"

   This will backup all GPOs in the domain wingtiptoys.com and store them in a date and time stamped folder 
   under \\wingdc01\backups\.

.EXAMPLE
   .\BackUp_GPOs.ps1 -Domain contoso.com -BackupFolder "c:\backups" -MigTable

   This will backup all GPOs in the domain contoso.com and store them in a date and time stamped folder 
   under c:\backups\. A migration table, MigrationTable.migtable, will also be created for manual editing.

.OUTPUTS
   Backup folder name in the format Year_Month_Day_HourMinuteSecond
   GpoDetails.xml
   WmiFilters.xml
   GpoInformation.csv
   MigrationTable.migtable (optional)

   EXIT CODES: 1 - GPMC not found

.NOTES
    THIS CODE-SAMPLE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR 
    FITNESS FOR A PARTICULAR PURPOSE.

    This sample is not supported under any Microsoft standard support program or service. 
    The script is provided AS IS without warranty of any kind. Microsoft further disclaims all
    implied warranties including, without limitation, any implied warranties of merchantability
    or of fitness for a particular purpose. The entire risk arising out of the use or performance
    of the sample and documentation remains with you. In no event shall Microsoft, its authors,
    or anyone else involved in the creation, production, or delivery of the script be liable for 
    any damages whatsoever (including, without limitation, damages for loss of business profits, 
    business interruption, loss of business information, or other pecuniary loss) arising out of 
    the use of or inability to use the sample or documentation, even if Microsoft has been advised 
    of the possibility of such damages, rising out of the use of or inability to use the sample script, 
    even if Microsoft has been advised of the possibility of such damages. 

#>
##########################################################################################################

#################################
## Script Options and Parameters
#################################

#Requires -version 3
#Requires -modules ActiveDirectory,GroupPolicy


#Define and validate parameters
[CmdletBinding()]
Param(
      #The target domain
      [parameter(Mandatory=$True,Position=1)]
      [ValidateScript({Get-ADDomain $_})] 
      [String]$Domain,

      #The backup folder
      [parameter(Mandatory=$True,Position=2)]
      [ValidateScript({Test-Path $_})]
      [String]$BackupFolder,

      #Whether to create a migration table
      [Switch] 
      $MigTable
      )


#Set strict mode to identify typographical errors (uncomment whilst editing script)
#Set-StrictMode -version Latest


##########################################################################################################

########
## Main
########

########################
##BACKUP FOLDER DETAILS
#Create a variable to represent a new backup folder
#(constructing the report name from date details and the supplied backup folder)
$Date = Get-Date

$SubBackupFolder = "$BackupFolder\" + `
                   "$($Date.Year)_" + `
                   "$("{0:D2}" -f $Date.Month)_" + `
                   "$("{0:D2}" -f $Date.Day)_" + `
                   "$("{0:D2}" -f $Date.Hour)" + `
                   "$("{0:D2}" -f $Date.Minute)" + `
                   "$("{0:D2}" -f $Date.Second)"


##################
##BACKUP ALL GPOs
#Create the backup folder
New-Item -ItemType Directory -Path $SubBackupFolder | Out-Null


#Make sure the backup folder has been created
If (Test-Path -Path $SubBackupFolder) {

    #Connect to the supplied domain
    $TargetDomain = Get-ADDomain $Domain
    

    #Obtain the domain FQDN
    $DomainFQDN = $TargetDomain.DNSRoot


    #Obtain the domain DN
    $DomainDN = $TargetDomain.DistinguishedName
    

    #Backup all the GPOs found in the domain
$GPOs = Get-GPO -All | where {$_.DisplayName -like '*win7*'}
foreach ($GPO in $GPOs) {
     $Backups += (Backup-GPO -Name $GPO.DisplayName) }


        #Instantiate an object for Group Policy Management (GPMC required)
        Try {

            $GPM = New-Object -ComObject GPMgmt.GPM
    
        }   #End of Try...
    
        Catch {

            #Display exit message to console
            $Message = "ERROR: Unable to connect to GPMC. Please check that it is installed."
            Write-Host
            Write-Error $Message
  
            #Exit the script
            Exit 1
    
        }   #End of Catch...


    #Import the GPM API constants
    $Constants = $GPM.getConstants()


    #Connect to the supplied domain
    $GpmDomain = $GPM.GetDomain($DomainFQDN,$Null,$Constants.UseAnyDc)



    ###################################
    ##COLLECT SPECIFIC GPO INFORMATION
    #Loop through each backed-up GPO
    ForEach ($Backup in $Backups) {

        #Get the GPO GUID for our target GPO
        $GpoGuid = $Backup.GpoId


        #Get the backup GUID for our target GPO
        $BackupGuid = $Backup.Id
        

        #Instantiate an object for the relevant GPO using GPM
        $GPO = $GpmDomain.GetGPO("{$GpoGuid}")


        #Get the GPO DisplayName property
        $GpoName = $GPO.DisplayName

            
            ##Retrieve SOM Information
            #Create a GPM search criteria object
            $GpmSearchCriteria = $GPM.CreateSearchCriteria()


            #Configure search critera for SOM links against a GPO
            $GpmSearchCriteria.Add($Constants.SearchPropertySOMLinks,$Constants.SearchOpContains,$GPO)


            #Perform the search
            $SOMs = $GpmDomain.SearchSOMs($GpmSearchCriteria)

        
            #Empty the SomPath variable
            $SomInfo = $Null

        
                #Loop through any SOMs returned and write them to a variable
                ForEach ($SOM in $SOMs) {

                    #Capture the SOM Distinguished Name
                    $SomDN = $SOM.Path

                
                    #Capture Block Inheritance state
                    $SomInheritance = $SOM.GPOInheritanceBlocked

                
                    #Get GPO Link information for the SOM
                    $GpoLinks = (Get-GPInheritance -Target $SomDN).GpoLinks


                        #Loop through the GPO Link information and match info that relates to our current GPO
                        ForEach ($GpoLink in $GpoLinks) {

                            If ($GpoLink.DisplayName -eq $GpoName) {

                                #Capture the GPO link status
                                $LinkEnabled = $GpoLink.Enabled


                                #Capture the GPO precedence order
                                $LinkOrder = $GpoLink.Order


                                #Capture Enforced state
                                $LinkEnforced = $GpoLink.Enforced


                            }   #End of If ($GpoLink.DisplayName -eq $GpoName)


                        }   #End of ForEach ($GpoLink in $GpoLinks)


                #Append the SOM DN, link status, link order and Block Inheritance info to $SomInfo
                [Array]$SomInfo += "$SomDN`:$SomInheritance`:$LinkEnabled`:$LinkOrder`:$LinkEnforced"
            
            
                }   #End of ForEach ($SOM in $SOMs)...


        ##Obtain WMI Filter path using Get-GPO
        $WmiFilter = (Get-GPO -Guid $GpoGuid).WMiFilter.Path
        
        #Split the value down and use the ID portion of the array
        $WMiFilter = ($WmiFilter -split "`"")[1]


        #Add selected GPO properties to a custom GPO object
        $GpoInfo = [PSCustomObject]@{

                BackupGuid = $BackupGuid
                Name = $GpoName
                GpoGuid = $GpoGuid
                SOMs = $SomInfo
                DomainDN = $DomainDN
                WmiFilter = $WmiFilter
        
        }   #End of $Properties...

        
        #Add our new object to an array
        [Array]$TotalGPOs += $GpoInfo


    }   #End of ForEach ($Backup in $Backups)...



    #####################
    ##BACKUP WMI FILTERS
    #Connect to the Active Directory to get details of the WMI filters
    $WmiFilters = Get-ADObject -Filter 'objectClass -eq "msWMI-Som"' `
                               -Properties msWMI-Author, msWMI-ID, msWMI-Name, msWMI-Parm1, msWMI-Parm2 `
                               -ErrorAction SilentlyContinue



    ######################
    ##CREATE REPORT FILES
    ##XML reports
    #Create a variable for the XML file representing custom information about the backed up GPOs
    $CustomGpoXML = "$SubBackupFolder\GpoDetails.xml"

    #Export our array of custom GPO objects to XML so they can be easily re-imported as objects
    $TotalGPOs | Export-Clixml -Path $CustomGpoXML

    #If $WMIFilters contains objects write these to an XML file
    If ($WmiFilters) {

        #Create a variable for the XML file representing the WMI filters
        $WmiXML = "$SubBackupFolder\WmiFilters.xml"

        #Export our array of WMI filters to XML so they can be easily re-imported as objects
        $WmiFilters | Export-Clixml -Path $WmiXML

    }   #End of If ($WmiFilters)


    ##CSV report
    #Create a variable for the CSV file that will contain the SOM (Scope of Management) information for each backed-up GPO
    $SOMReportCSV = "$SubBackupFolder\GpoInformation.csv"


    #Now, let's create the CSV report 
    ForEach ($CustomGPO in $TotalGPOs) {
            
        #Start constructing the CSV file line entry for the current GPO
        $CSVLine = "`"$($CustomGPO.Name)`",`"{$($CustomGPO.GPOGuid)}`","


        #Expand the SOMs property of the current object
        $CustomSOMs = $CustomGPO.SOMs


            #Loop through any SOMs returned
            ForEach ($CustomSOM in $CustomSOMs) {

                #Append the SOM path to our CSV line
                $CSVLine += "`"$CustomSOM`","

         
           }   #End of ForEach ($CustomSOM in $CustomSOMs)...


       #Write the newly constructed CSV line to the report
       Add-Content -Path $SOMReportCSV -Value $CSVLine


    }   #End of ForEach ($CustomGPO in $TotalGPOs)...


    ###########
    ##MIGTABLE
    #Check whether a migration table should be created
    If ($MigTable) {

        #Create a variable for the migration table
        $MigrationFile = "$SubBackupFolder\MigrationTable.migtable"

        #Create a migration table 
        $MigrationTable = $GPM.CreateMigrationTable()


        #Connect to the backup directory
        $GpmBackupDir = $GPM.GetBackUpDir($SubBackupFolder)


        #Reset the GPM search criterea
        $GpmSearchCriteria = $GPM.CreateSearchCriteria()


        #Configure search critera for the most recent backup
        $GpmSearchCriteria.Add($Constants.SearchPropertyBackupMostRecent,$Constants.SearchOpEquals,$True)
   

        #Get GPO information
        $BackedUpGPOs = $GpmBackupDir.SearchBackups($GpmSearchCriteria)


            #Add the information to our migration table
            ForEach ($BackedUpGPO in $BackedUpGPOs) {

                $MigrationTable.Add($Constants.ProcessSecurity,$BackedUpGPO)
        
            }   #End of ForEach ($BackedUpGPO in $BackedUpGPOs)...


        #Save the migration table
        $MigrationTable.Save($MigrationFile)


    }   #End of If ($MigTable)...


}   #End of If (Test-Path $SubBackupFolder)...

Open in new window

0
 

Author Comment

by:levertm
ID: 39860503
I just tried it Dan, came back with an error. The extra code is from the original script, it's needed for Path and Domain. The error is as follows, apologies for the first letter being cut on each line:
S C:\Users\user1\Desktop\gpo> .\BackUp_GPOs.ps1 -MigTable

mdlet BackUp_GPOs.ps1 at command pipeline position 1
upply values for the following parameters:
omain: van.domain.maj.ca
ackupFolder: C:\Users\user1\Desktop\gpo\backup

mdlet Backup-GPO at command pipeline position 1
upply values for the following parameters:
ath: $SubBackupFolder
ackup-GPO : The system cannot find the file specified. (Exception from HRESULT: 0x80070002)
t C:\Users\user1\Desktop\gpo\BackUp_GPOs.ps1:143 char:19
      $Backups += (Backup-GPO -Name $GPO.DisplayName) }
                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   + CategoryInfo          : NotSpecified: (:) [Backup-GPO], FileNotFoundException
   + FullyQualifiedErrorId : System.IO.FileNotFoundException,Microsoft.GroupPolicy.Commands.BackupGpoCommand


mdlet Backup-GPO at command pipeline position 1
upply values for the following parameters:
ath: C:\Users\user1\Desktop\gpo\backup

mdlet Backup-GPO at command pipeline position 1
upply values for the following parameters:
ath: C:\Users\user1\Desktop\gpo\backup
ethod invocation failed because [Microsoft.GroupPolicy.GpoBackup] doesn't contain a method named 'op_Addition'.
t C:\Users\user1\Desktop\gpo\BackUp_GPOs.ps1:143 char:6
      $Backups += (Backup-GPO -Name $GPO.DisplayName) }
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   + CategoryInfo          : InvalidOperation: (op_Addition:String) [], RuntimeException
   + FullyQualifiedErrorId : MethodNotFound

Open in new window

0
 
LVL 34

Expert Comment

by:Dan Craciun
ID: 39860550
OK, seems like Backup-GPO was missing a required parameter.

Try this:
##########################################################################################################
<#
.SYNOPSIS
    Backs up all GPOs from a specified domain and includes additional GPO information.

.DESCRIPTION
    The script backs up all GPOs in a target domain and captures additional GPO management information, such
    as Scope of Management, Block Inheritance, Link Enabled, Link Order, Link Enforced and WMI Filters.

    The backup can then be used by a partner script to mirror GPOs in a test domain.

    Details:
    * Creates a XML file containing PSCustomObjects used by partner import script
    * Creates a XML file WMI filter details used by partner import script
    * Creates a CSV file of additional information for readability
    * Additional backup information includes SOM (Scope of Management) Path, Block Inheritance, Link Enabled,
      Link Order', Link Enforced and WMI Filter data
    * Each CSV SOM entry is made up of "DistinguishedName:BlockInheritance:LinkEnabled:LinkOrder:LinkEnforced"
    * Option to create a Migration Table (to then be manually updated)

    Requirements: 
    * PowerShell GroupPolicy Module
    * PowerShell ActiveDirectory Module
    * Group Policy Management Console

.EXAMPLE
   .\BackUp_GPOs.ps1 -Domain wintiptoys.com -BackupFolder "\\wingdc01\backups\"

   This will backup all GPOs in the domain wingtiptoys.com and store them in a date and time stamped folder 
   under \\wingdc01\backups\.

.EXAMPLE
   .\BackUp_GPOs.ps1 -Domain contoso.com -BackupFolder "c:\backups" -MigTable

   This will backup all GPOs in the domain contoso.com and store them in a date and time stamped folder 
   under c:\backups\. A migration table, MigrationTable.migtable, will also be created for manual editing.

.OUTPUTS
   Backup folder name in the format Year_Month_Day_HourMinuteSecond
   GpoDetails.xml
   WmiFilters.xml
   GpoInformation.csv
   MigrationTable.migtable (optional)

   EXIT CODES: 1 - GPMC not found

.NOTES
    THIS CODE-SAMPLE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR 
    FITNESS FOR A PARTICULAR PURPOSE.

    This sample is not supported under any Microsoft standard support program or service. 
    The script is provided AS IS without warranty of any kind. Microsoft further disclaims all
    implied warranties including, without limitation, any implied warranties of merchantability
    or of fitness for a particular purpose. The entire risk arising out of the use or performance
    of the sample and documentation remains with you. In no event shall Microsoft, its authors,
    or anyone else involved in the creation, production, or delivery of the script be liable for 
    any damages whatsoever (including, without limitation, damages for loss of business profits, 
    business interruption, loss of business information, or other pecuniary loss) arising out of 
    the use of or inability to use the sample or documentation, even if Microsoft has been advised 
    of the possibility of such damages, rising out of the use of or inability to use the sample script, 
    even if Microsoft has been advised of the possibility of such damages. 

#>
##########################################################################################################

#################################
## Script Options and Parameters
#################################

#Requires -version 3
#Requires -modules ActiveDirectory,GroupPolicy


#Define and validate parameters
[CmdletBinding()]
Param(
      #The target domain
      [parameter(Mandatory=$True,Position=1)]
      [ValidateScript({Get-ADDomain $_})] 
      [String]$Domain,

      #The backup folder
      [parameter(Mandatory=$True,Position=2)]
      [ValidateScript({Test-Path $_})]
      [String]$BackupFolder,

      #Whether to create a migration table
      [Switch] 
      $MigTable
      )


#Set strict mode to identify typographical errors (uncomment whilst editing script)
#Set-StrictMode -version Latest


##########################################################################################################

########
## Main
########

########################
##BACKUP FOLDER DETAILS
#Create a variable to represent a new backup folder
#(constructing the report name from date details and the supplied backup folder)
$Date = Get-Date

$SubBackupFolder = "$BackupFolder\" + `
                   "$($Date.Year)_" + `
                   "$("{0:D2}" -f $Date.Month)_" + `
                   "$("{0:D2}" -f $Date.Day)_" + `
                   "$("{0:D2}" -f $Date.Hour)" + `
                   "$("{0:D2}" -f $Date.Minute)" + `
                   "$("{0:D2}" -f $Date.Second)"


##################
##BACKUP ALL GPOs
#Create the backup folder
New-Item -ItemType Directory -Path $SubBackupFolder | Out-Null


#Make sure the backup folder has been created
If (Test-Path -Path $SubBackupFolder) {

    #Connect to the supplied domain
    $TargetDomain = Get-ADDomain $Domain
    

    #Obtain the domain FQDN
    $DomainFQDN = $TargetDomain.DNSRoot


    #Obtain the domain DN
    $DomainDN = $TargetDomain.DistinguishedName
    

    #Backup all the GPOs found in the domain
$GPOs = Get-GPO -All | where {$_.DisplayName -like '*win7*'}
foreach ($GPO in $GPOs) {
     $Backups += (Backup-GPO -All -Path $SubBackupFolder -Domain $DomainFQDN) }


        #Instantiate an object for Group Policy Management (GPMC required)
        Try {

            $GPM = New-Object -ComObject GPMgmt.GPM
    
        }   #End of Try...
    
        Catch {

            #Display exit message to console
            $Message = "ERROR: Unable to connect to GPMC. Please check that it is installed."
            Write-Host
            Write-Error $Message
  
            #Exit the script
            Exit 1
    
        }   #End of Catch...


    #Import the GPM API constants
    $Constants = $GPM.getConstants()


    #Connect to the supplied domain
    $GpmDomain = $GPM.GetDomain($DomainFQDN,$Null,$Constants.UseAnyDc)



    ###################################
    ##COLLECT SPECIFIC GPO INFORMATION
    #Loop through each backed-up GPO
    ForEach ($Backup in $Backups) {

        #Get the GPO GUID for our target GPO
        $GpoGuid = $Backup.GpoId


        #Get the backup GUID for our target GPO
        $BackupGuid = $Backup.Id
        

        #Instantiate an object for the relevant GPO using GPM
        $GPO = $GpmDomain.GetGPO("{$GpoGuid}")


        #Get the GPO DisplayName property
        $GpoName = $GPO.DisplayName

            
            ##Retrieve SOM Information
            #Create a GPM search criteria object
            $GpmSearchCriteria = $GPM.CreateSearchCriteria()


            #Configure search critera for SOM links against a GPO
            $GpmSearchCriteria.Add($Constants.SearchPropertySOMLinks,$Constants.SearchOpContains,$GPO)


            #Perform the search
            $SOMs = $GpmDomain.SearchSOMs($GpmSearchCriteria)

        
            #Empty the SomPath variable
            $SomInfo = $Null

        
                #Loop through any SOMs returned and write them to a variable
                ForEach ($SOM in $SOMs) {

                    #Capture the SOM Distinguished Name
                    $SomDN = $SOM.Path

                
                    #Capture Block Inheritance state
                    $SomInheritance = $SOM.GPOInheritanceBlocked

                
                    #Get GPO Link information for the SOM
                    $GpoLinks = (Get-GPInheritance -Target $SomDN).GpoLinks


                        #Loop through the GPO Link information and match info that relates to our current GPO
                        ForEach ($GpoLink in $GpoLinks) {

                            If ($GpoLink.DisplayName -eq $GpoName) {

                                #Capture the GPO link status
                                $LinkEnabled = $GpoLink.Enabled


                                #Capture the GPO precedence order
                                $LinkOrder = $GpoLink.Order


                                #Capture Enforced state
                                $LinkEnforced = $GpoLink.Enforced


                            }   #End of If ($GpoLink.DisplayName -eq $GpoName)


                        }   #End of ForEach ($GpoLink in $GpoLinks)


                #Append the SOM DN, link status, link order and Block Inheritance info to $SomInfo
                [Array]$SomInfo += "$SomDN`:$SomInheritance`:$LinkEnabled`:$LinkOrder`:$LinkEnforced"
            
            
                }   #End of ForEach ($SOM in $SOMs)...


        ##Obtain WMI Filter path using Get-GPO
        $WmiFilter = (Get-GPO -Guid $GpoGuid).WMiFilter.Path
        
        #Split the value down and use the ID portion of the array
        $WMiFilter = ($WmiFilter -split "`"")[1]


        #Add selected GPO properties to a custom GPO object
        $GpoInfo = [PSCustomObject]@{

                BackupGuid = $BackupGuid
                Name = $GpoName
                GpoGuid = $GpoGuid
                SOMs = $SomInfo
                DomainDN = $DomainDN
                WmiFilter = $WmiFilter
        
        }   #End of $Properties...

        
        #Add our new object to an array
        [Array]$TotalGPOs += $GpoInfo


    }   #End of ForEach ($Backup in $Backups)...



    #####################
    ##BACKUP WMI FILTERS
    #Connect to the Active Directory to get details of the WMI filters
    $WmiFilters = Get-ADObject -Filter 'objectClass -eq "msWMI-Som"' `
                               -Properties msWMI-Author, msWMI-ID, msWMI-Name, msWMI-Parm1, msWMI-Parm2 `
                               -ErrorAction SilentlyContinue



    ######################
    ##CREATE REPORT FILES
    ##XML reports
    #Create a variable for the XML file representing custom information about the backed up GPOs
    $CustomGpoXML = "$SubBackupFolder\GpoDetails.xml"

    #Export our array of custom GPO objects to XML so they can be easily re-imported as objects
    $TotalGPOs | Export-Clixml -Path $CustomGpoXML

    #If $WMIFilters contains objects write these to an XML file
    If ($WmiFilters) {

        #Create a variable for the XML file representing the WMI filters
        $WmiXML = "$SubBackupFolder\WmiFilters.xml"

        #Export our array of WMI filters to XML so they can be easily re-imported as objects
        $WmiFilters | Export-Clixml -Path $WmiXML

    }   #End of If ($WmiFilters)


    ##CSV report
    #Create a variable for the CSV file that will contain the SOM (Scope of Management) information for each backed-up GPO
    $SOMReportCSV = "$SubBackupFolder\GpoInformation.csv"


    #Now, let's create the CSV report 
    ForEach ($CustomGPO in $TotalGPOs) {
            
        #Start constructing the CSV file line entry for the current GPO
        $CSVLine = "`"$($CustomGPO.Name)`",`"{$($CustomGPO.GPOGuid)}`","


        #Expand the SOMs property of the current object
        $CustomSOMs = $CustomGPO.SOMs


            #Loop through any SOMs returned
            ForEach ($CustomSOM in $CustomSOMs) {

                #Append the SOM path to our CSV line
                $CSVLine += "`"$CustomSOM`","

         
           }   #End of ForEach ($CustomSOM in $CustomSOMs)...


       #Write the newly constructed CSV line to the report
       Add-Content -Path $SOMReportCSV -Value $CSVLine


    }   #End of ForEach ($CustomGPO in $TotalGPOs)...


    ###########
    ##MIGTABLE
    #Check whether a migration table should be created
    If ($MigTable) {

        #Create a variable for the migration table
        $MigrationFile = "$SubBackupFolder\MigrationTable.migtable"

        #Create a migration table 
        $MigrationTable = $GPM.CreateMigrationTable()


        #Connect to the backup directory
        $GpmBackupDir = $GPM.GetBackUpDir($SubBackupFolder)


        #Reset the GPM search criterea
        $GpmSearchCriteria = $GPM.CreateSearchCriteria()


        #Configure search critera for the most recent backup
        $GpmSearchCriteria.Add($Constants.SearchPropertyBackupMostRecent,$Constants.SearchOpEquals,$True)
   

        #Get GPO information
        $BackedUpGPOs = $GpmBackupDir.SearchBackups($GpmSearchCriteria)


            #Add the information to our migration table
            ForEach ($BackedUpGPO in $BackedUpGPOs) {

                $MigrationTable.Add($Constants.ProcessSecurity,$BackedUpGPO)
        
            }   #End of ForEach ($BackedUpGPO in $BackedUpGPOs)...


        #Save the migration table
        $MigrationTable.Save($MigrationFile)


    }   #End of If ($MigTable)...


}   #End of If (Test-Path $SubBackupFolder)...

Open in new window

0
 
LVL 34

Expert Comment

by:Dan Craciun
ID: 39860571
BTW, after reading what Backup-GPO actually does, I don't think your changes will work.
You will simply have all the attributes, but repeated as many times as there's GPO's that contain "win7"
0
 
LVL 34

Expert Comment

by:Dan Craciun
ID: 39860604
Modified code, to only backup GPO's that contain "win7" in their DisplayName. See line 193
##########################################################################################################
<#
.SYNOPSIS
    Backs up all GPOs from a specified domain and includes additional GPO information.

.DESCRIPTION
    The script backs up all GPOs in a target domain and captures additional GPO management information, such
    as Scope of Management, Block Inheritance, Link Enabled, Link Order, Link Enforced and WMI Filters.

    The backup can then be used by a partner script to mirror GPOs in a test domain.

    Details:
    * Creates a XML file containing PSCustomObjects used by partner import script
    * Creates a XML file WMI filter details used by partner import script
    * Creates a CSV file of additional information for readability
    * Additional backup information includes SOM (Scope of Management) Path, Block Inheritance, Link Enabled,
      Link Order', Link Enforced and WMI Filter data
    * Each CSV SOM entry is made up of "DistinguishedName:BlockInheritance:LinkEnabled:LinkOrder:LinkEnforced"
    * Option to create a Migration Table (to then be manually updated)

    Requirements: 
    * PowerShell GroupPolicy Module
    * PowerShell ActiveDirectory Module
    * Group Policy Management Console

.EXAMPLE
   .\BackUp_GPOs.ps1 -Domain wintiptoys.com -BackupFolder "\\wingdc01\backups\"

   This will backup all GPOs in the domain wingtiptoys.com and store them in a date and time stamped folder 
   under \\wingdc01\backups\.

.EXAMPLE
   .\BackUp_GPOs.ps1 -Domain contoso.com -BackupFolder "c:\backups" -MigTable

   This will backup all GPOs in the domain contoso.com and store them in a date and time stamped folder 
   under c:\backups\. A migration table, MigrationTable.migtable, will also be created for manual editing.

.OUTPUTS
   Backup folder name in the format Year_Month_Day_HourMinuteSecond
   GpoDetails.xml
   WmiFilters.xml
   GpoInformation.csv
   MigrationTable.migtable (optional)

   EXIT CODES: 1 - GPMC not found

.NOTES
    THIS CODE-SAMPLE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR 
    FITNESS FOR A PARTICULAR PURPOSE.

    This sample is not supported under any Microsoft standard support program or service. 
    The script is provided AS IS without warranty of any kind. Microsoft further disclaims all
    implied warranties including, without limitation, any implied warranties of merchantability
    or of fitness for a particular purpose. The entire risk arising out of the use or performance
    of the sample and documentation remains with you. In no event shall Microsoft, its authors,
    or anyone else involved in the creation, production, or delivery of the script be liable for 
    any damages whatsoever (including, without limitation, damages for loss of business profits, 
    business interruption, loss of business information, or other pecuniary loss) arising out of 
    the use of or inability to use the sample or documentation, even if Microsoft has been advised 
    of the possibility of such damages, rising out of the use of or inability to use the sample script, 
    even if Microsoft has been advised of the possibility of such damages. 

#>
##########################################################################################################

#################################
## Script Options and Parameters
#################################

#Requires -version 3
#Requires -modules ActiveDirectory,GroupPolicy


#Define and validate parameters
[CmdletBinding()]
Param(
      #The target domain
      [parameter(Mandatory=$True,Position=1)]
      [ValidateScript({Get-ADDomain $_})] 
      [String]$Domain,

      #The backup folder
      [parameter(Mandatory=$True,Position=2)]
      [ValidateScript({Test-Path $_})]
      [String]$BackupFolder,

      #Whether to create a migration table
      [Switch] 
      $MigTable
      )


#Set strict mode to identify typographical errors (uncomment whilst editing script)
#Set-StrictMode -version Latest


##########################################################################################################

########
## Main
########

########################
##BACKUP FOLDER DETAILS
#Create a variable to represent a new backup folder
#(constructing the report name from date details and the supplied backup folder)
$Date = Get-Date

$SubBackupFolder = "$BackupFolder\" + `
                   "$($Date.Year)_" + `
                   "$("{0:D2}" -f $Date.Month)_" + `
                   "$("{0:D2}" -f $Date.Day)_" + `
                   "$("{0:D2}" -f $Date.Hour)" + `
                   "$("{0:D2}" -f $Date.Minute)" + `
                   "$("{0:D2}" -f $Date.Second)"


##################
##BACKUP ALL GPOs
#Create the backup folder
New-Item -ItemType Directory -Path $SubBackupFolder | Out-Null


#Make sure the backup folder has been created
If (Test-Path -Path $SubBackupFolder) {

    #Connect to the supplied domain
    $TargetDomain = Get-ADDomain $Domain
    

    #Obtain the domain FQDN
    $DomainFQDN = $TargetDomain.DNSRoot


    #Obtain the domain DN
    $DomainDN = $TargetDomain.DistinguishedName
    

    #Backup all the GPOs found in the domain
    $Backups = Backup-GPO -All -Path $SubBackupFolder -Domain $DomainFQDN -Comment "Scripted backup created by $env:userdomain\$env:username on $(Get-Date -format d)"


        #Instantiate an object for Group Policy Management (GPMC required)
        Try {

            $GPM = New-Object -ComObject GPMgmt.GPM
    
        }   #End of Try...
    
        Catch {

            #Display exit message to console
            $Message = "ERROR: Unable to connect to GPMC. Please check that it is installed."
            Write-Host
            Write-Error $Message
  
            #Exit the script
            Exit 1
    
        }   #End of Catch...


    #Import the GPM API constants
    $Constants = $GPM.getConstants()


    #Connect to the supplied domain
    $GpmDomain = $GPM.GetDomain($DomainFQDN,$Null,$Constants.UseAnyDc)



    ###################################
    ##COLLECT SPECIFIC GPO INFORMATION
    #Loop through each backed-up GPO
    ForEach ($Backup in $Backups) {

        #Get the GPO GUID for our target GPO
        $GpoGuid = $Backup.GpoId


        #Get the backup GUID for our target GPO
        $BackupGuid = $Backup.Id
        

        #Instantiate an object for the relevant GPO using GPM
        $GPO = $GpmDomain.GetGPO("{$GpoGuid}")


        #Get the GPO DisplayName property
        $GpoName = $GPO.DisplayName

            if ($GpoName -like "*win7*") {
            ##Retrieve SOM Information
            #Create a GPM search criteria object
            $GpmSearchCriteria = $GPM.CreateSearchCriteria()


            #Configure search critera for SOM links against a GPO
            $GpmSearchCriteria.Add($Constants.SearchPropertySOMLinks,$Constants.SearchOpContains,$GPO)


            #Perform the search
            $SOMs = $GpmDomain.SearchSOMs($GpmSearchCriteria)

        
            #Empty the SomPath variable
            $SomInfo = $Null

        
                #Loop through any SOMs returned and write them to a variable
                ForEach ($SOM in $SOMs) {

                    #Capture the SOM Distinguished Name
                    $SomDN = $SOM.Path

                
                    #Capture Block Inheritance state
                    $SomInheritance = $SOM.GPOInheritanceBlocked

                
                    #Get GPO Link information for the SOM
                    $GpoLinks = (Get-GPInheritance -Target $SomDN).GpoLinks


                        #Loop through the GPO Link information and match info that relates to our current GPO
                        ForEach ($GpoLink in $GpoLinks) {

                            If ($GpoLink.DisplayName -eq $GpoName) {

                                #Capture the GPO link status
                                $LinkEnabled = $GpoLink.Enabled


                                #Capture the GPO precedence order
                                $LinkOrder = $GpoLink.Order


                                #Capture Enforced state
                                $LinkEnforced = $GpoLink.Enforced


                            }   #End of If ($GpoLink.DisplayName -eq $GpoName)


                        }   #End of ForEach ($GpoLink in $GpoLinks)


                #Append the SOM DN, link status, link order and Block Inheritance info to $SomInfo
                [Array]$SomInfo += "$SomDN`:$SomInheritance`:$LinkEnabled`:$LinkOrder`:$LinkEnforced"
            
            
                }   #End of ForEach ($SOM in $SOMs)...


        ##Obtain WMI Filter path using Get-GPO
        $WmiFilter = (Get-GPO -Guid $GpoGuid).WMiFilter.Path
        
        #Split the value down and use the ID portion of the array
        $WMiFilter = ($WmiFilter -split "`"")[1]


        #Add selected GPO properties to a custom GPO object
        $GpoInfo = [PSCustomObject]@{

                BackupGuid = $BackupGuid
                Name = $GpoName
                GpoGuid = $GpoGuid
                SOMs = $SomInfo
                DomainDN = $DomainDN
                WmiFilter = $WmiFilter
        
        }   #End of $Properties...

        
        #Add our new object to an array
        [Array]$TotalGPOs += $GpoInfo

	}
    }   #End of ForEach ($Backup in $Backups)...



    #####################
    ##BACKUP WMI FILTERS
    #Connect to the Active Directory to get details of the WMI filters
    $WmiFilters = Get-ADObject -Filter 'objectClass -eq "msWMI-Som"' `
                               -Properties msWMI-Author, msWMI-ID, msWMI-Name, msWMI-Parm1, msWMI-Parm2 `
                               -ErrorAction SilentlyContinue



    ######################
    ##CREATE REPORT FILES
    ##XML reports
    #Create a variable for the XML file representing custom information about the backed up GPOs
    $CustomGpoXML = "$SubBackupFolder\GpoDetails.xml"

    #Export our array of custom GPO objects to XML so they can be easily re-imported as objects
    $TotalGPOs | Export-Clixml -Path $CustomGpoXML

    #If $WMIFilters contains objects write these to an XML file
    If ($WmiFilters) {

        #Create a variable for the XML file representing the WMI filters
        $WmiXML = "$SubBackupFolder\WmiFilters.xml"

        #Export our array of WMI filters to XML so they can be easily re-imported as objects
        $WmiFilters | Export-Clixml -Path $WmiXML

    }   #End of If ($WmiFilters)


    ##CSV report
    #Create a variable for the CSV file that will contain the SOM (Scope of Management) information for each backed-up GPO
    $SOMReportCSV = "$SubBackupFolder\GpoInformation.csv"


    #Now, let's create the CSV report 
    ForEach ($CustomGPO in $TotalGPOs) {
            
        #Start constructing the CSV file line entry for the current GPO
        $CSVLine = "`"$($CustomGPO.Name)`",`"{$($CustomGPO.GPOGuid)}`","


        #Expand the SOMs property of the current object
        $CustomSOMs = $CustomGPO.SOMs


            #Loop through any SOMs returned
            ForEach ($CustomSOM in $CustomSOMs) {

                #Append the SOM path to our CSV line
                $CSVLine += "`"$CustomSOM`","

         
           }   #End of ForEach ($CustomSOM in $CustomSOMs)...


       #Write the newly constructed CSV line to the report
       Add-Content -Path $SOMReportCSV -Value $CSVLine


    }   #End of ForEach ($CustomGPO in $TotalGPOs)...


    ###########
    ##MIGTABLE
    #Check whether a migration table should be created
    If ($MigTable) {

        #Create a variable for the migration table
        $MigrationFile = "$SubBackupFolder\MigrationTable.migtable"

        #Create a migration table 
        $MigrationTable = $GPM.CreateMigrationTable()


        #Connect to the backup directory
        $GpmBackupDir = $GPM.GetBackUpDir($SubBackupFolder)


        #Reset the GPM search criterea
        $GpmSearchCriteria = $GPM.CreateSearchCriteria()


        #Configure search critera for the most recent backup
        $GpmSearchCriteria.Add($Constants.SearchPropertyBackupMostRecent,$Constants.SearchOpEquals,$True)
   

        #Get GPO information
        $BackedUpGPOs = $GpmBackupDir.SearchBackups($GpmSearchCriteria)


            #Add the information to our migration table
            ForEach ($BackedUpGPO in $BackedUpGPOs) {

                $MigrationTable.Add($Constants.ProcessSecurity,$BackedUpGPO)
        
            }   #End of ForEach ($BackedUpGPO in $BackedUpGPOs)...


        #Save the migration table
        $MigrationTable.Save($MigrationFile)


    }   #End of If ($MigTable)...


}   #End of If (Test-Path $SubBackupFolder)...

Open in new window

0
 

Author Comment

by:levertm
ID: 39864818
Hi Dan,

I was away from my workstation for the weeked. Apologies fo the late response..

I tried your latest modification and while the script does backup all GPO's that have "Win7" in their name, it still fails to output the results into GpoDetails.xml file. Unfortunately without this file my automation process is null.

Where as the original script outputs a GpoDetails.xml file.
0
 
LVL 39

Accepted Solution

by:
footech earned 500 total points
ID: 39872220
I think you just about had it with the first code you posted.  You just needed store the info in the $Backups variable.  I removed a lot of the white space.  My mod to the code is on lines 137-139.  I tested and it generates the .xml file.  Dan's code in http:#a39860550 would have worked if it had kept the -name parameter for Backup-GPO (instead of using -all) and defined $Backups beforehand as an empty array.
Using ForEach-Object cmdlet here instead of the foreach statement is cleaner and avoids some unnecessary creation of variables.
##########################################################################################################
<#
.SYNOPSIS
    Backs up all GPOs from a specified domain and includes additional GPO information.

.DESCRIPTION
    The script backs up all GPOs in a target domain and captures additional GPO management information, such
    as Scope of Management, Block Inheritance, Link Enabled, Link Order, Link Enforced and WMI Filters.

    The backup can then be used by a partner script to mirror GPOs in a test domain.

    Details:
    * Creates a XML file containing PSCustomObjects used by partner import script
    * Creates a XML file WMI filter details used by partner import script
    * Creates a CSV file of additional information for readability
    * Additional backup information includes SOM (Scope of Management) Path, Block Inheritance, Link Enabled,
      Link Order', Link Enforced and WMI Filter data
    * Each CSV SOM entry is made up of "DistinguishedName:BlockInheritance:LinkEnabled:LinkOrder:LinkEnforced"
    * Option to create a Migration Table (to then be manually updated)

    Requirements: 
    * PowerShell GroupPolicy Module
    * PowerShell ActiveDirectory Module
    * Group Policy Management Console

.EXAMPLE
   .\BackUp_GPOs.ps1 -Domain wintiptoys.com -BackupFolder "\\wingdc01\backups\"

   This will backup all GPOs in the domain wingtiptoys.com and store them in a date and time stamped folder 
   under \\wingdc01\backups\.

.EXAMPLE
   .\BackUp_GPOs.ps1 -Domain contoso.com -BackupFolder "c:\backups" -MigTable

   This will backup all GPOs in the domain contoso.com and store them in a date and time stamped folder 
   under c:\backups\. A migration table, MigrationTable.migtable, will also be created for manual editing.

.OUTPUTS
   Backup folder name in the format Year_Month_Day_HourMinuteSecond
   GpoDetails.xml
   WmiFilters.xml
   GpoInformation.csv
   MigrationTable.migtable (optional)

   EXIT CODES: 1 - GPMC not found

.NOTES
    THIS CODE-SAMPLE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR 
    FITNESS FOR A PARTICULAR PURPOSE.

    This sample is not supported under any Microsoft standard support program or service. 
    The script is provided AS IS without warranty of any kind. Microsoft further disclaims all
    implied warranties including, without limitation, any implied warranties of merchantability
    or of fitness for a particular purpose. The entire risk arising out of the use or performance
    of the sample and documentation remains with you. In no event shall Microsoft, its authors,
    or anyone else involved in the creation, production, or delivery of the script be liable for 
    any damages whatsoever (including, without limitation, damages for loss of business profits, 
    business interruption, loss of business information, or other pecuniary loss) arising out of 
    the use of or inability to use the sample or documentation, even if Microsoft has been advised 
    of the possibility of such damages, rising out of the use of or inability to use the sample script, 
    even if Microsoft has been advised of the possibility of such damages. 

#>
##########################################################################################################

#################################
## Script Options and Parameters
#################################

#Requires -version 3
#Requires -modules ActiveDirectory,GroupPolicy


#Define and validate parameters
[CmdletBinding()]
Param(
      #The target domain
      [parameter(Mandatory=$True,Position=1)]
      [ValidateScript({Get-ADDomain $_})] 
      [String]$Domain,

      #The backup folder
      [parameter(Mandatory=$True,Position=2)]
      [ValidateScript({Test-Path $_})]
      [String]$BackupFolder,

      #Whether to create a migration table
      [Switch] 
      $MigTable
      )


#Set strict mode to identify typographical errors (uncomment whilst editing script)
#Set-StrictMode -version Latest


##########################################################################################################

########
## Main
########

########################
##BACKUP FOLDER DETAILS
#Create a variable to represent a new backup folder
#(constructing the report name from date details and the supplied backup folder)
$Date = Get-Date

$SubBackupFolder = "$BackupFolder\" + `
                   "$($Date.Year)_" + `
                   "$("{0:D2}" -f $Date.Month)_" + `
                   "$("{0:D2}" -f $Date.Day)_" + `
                   "$("{0:D2}" -f $Date.Hour)" + `
                   "$("{0:D2}" -f $Date.Minute)" + `
                   "$("{0:D2}" -f $Date.Second)"


##################
##BACKUP ALL GPOs
#Create the backup folder
New-Item -ItemType Directory -Path $SubBackupFolder | Out-Null


#Make sure the backup folder has been created
If (Test-Path -Path $SubBackupFolder) {

    #Connect to the supplied domain
    $TargetDomain = Get-ADDomain $Domain   

    #Obtain the domain FQDN
    $DomainFQDN = $TargetDomain.DNSRoot

    #Obtain the domain DN
    $DomainDN = $TargetDomain.DistinguishedName

    #Backup all the GPOs found in the domain and filtered by DisplayName
    $Backups = Get-GPO -All | Where {$_.DisplayName -like '*win7*'}  | Select -ExpandProperty DisplayName | 
     ForEach { Backup-GPO -Name $_ -Path $SubBackupFolder -Domain $DomainFQDN -Comment "Scripted backup created by $env:userdomain\$env:username on $(Get-Date -format d)" }

    #Instantiate an object for Group Policy Management (GPMC required)
    Try {
        $GPM = New-Object -ComObject GPMgmt.GPM
    }   #End of Try...   
    Catch {
        #Display exit message to console
        $Message = "ERROR: Unable to connect to GPMC. Please check that it is installed."
        Write-Host
        Write-Error $Message
  
        #Exit the script
        Exit 1
    }   #End of Catch...

    #Import the GPM API constants
    $Constants = $GPM.getConstants()

    #Connect to the supplied domain
    $GpmDomain = $GPM.GetDomain($DomainFQDN,$Null,$Constants.UseAnyDc)

    ###################################
    ##COLLECT SPECIFIC GPO INFORMATION
    #Loop through each backed-up GPO
    ForEach ($Backup in $Backups) {
        #Get the GPO GUID for our target GPO
        $GpoGuid = $Backup.GpoId

        #Get the backup GUID for our target GPO
        $BackupGuid = $Backup.Id
       
        #Instantiate an object for the relevant GPO using GPM
        $GPO = $GpmDomain.GetGPO("{$GpoGuid}")

        #Get the GPO DisplayName property
        $GpoName = $GPO.DisplayName
            
        ##Retrieve SOM Information
        #Create a GPM search criteria object
        $GpmSearchCriteria = $GPM.CreateSearchCriteria()

        #Configure search critera for SOM links against a GPO
        $GpmSearchCriteria.Add($Constants.SearchPropertySOMLinks,$Constants.SearchOpContains,$GPO)

        #Perform the search
        $SOMs = $GpmDomain.SearchSOMs($GpmSearchCriteria)
        
        #Empty the SomPath variable
        $SomInfo = $Null
      
        #Loop through any SOMs returned and write them to a variable
        ForEach ($SOM in $SOMs) {

            #Capture the SOM Distinguished Name
            $SomDN = $SOM.Path
                
            #Capture Block Inheritance state
            $SomInheritance = $SOM.GPOInheritanceBlocked
                
            #Get GPO Link information for the SOM
            $GpoLinks = (Get-GPInheritance -Target $SomDN).GpoLinks

            #Loop through the GPO Link information and match info that relates to our current GPO
            ForEach ($GpoLink in $GpoLinks) {

                If ($GpoLink.DisplayName -eq $GpoName) {

                    #Capture the GPO link status
                    $LinkEnabled = $GpoLink.Enabled


                    #Capture the GPO precedence order
                    $LinkOrder = $GpoLink.Order


                    #Capture Enforced state
                    $LinkEnforced = $GpoLink.Enforced

                }   #End of If ($GpoLink.DisplayName -eq $GpoName)

            }   #End of ForEach ($GpoLink in $GpoLinks)

            #Append the SOM DN, link status, link order and Block Inheritance info to $SomInfo
            [Array]$SomInfo += "$SomDN`:$SomInheritance`:$LinkEnabled`:$LinkOrder`:$LinkEnforced"
                     
        }   #End of ForEach ($SOM in $SOMs)...

        ##Obtain WMI Filter path using Get-GPO
        $WmiFilter = (Get-GPO -Guid $GpoGuid).WMiFilter.Path
        
        #Split the value down and use the ID portion of the array
        $WMiFilter = ($WmiFilter -split "`"")[1]

        #Add selected GPO properties to a custom GPO object
        $GpoInfo = [PSCustomObject]@{

                BackupGuid = $BackupGuid
                Name = $GpoName
                GpoGuid = $GpoGuid
                SOMs = $SomInfo
                DomainDN = $DomainDN
                WmiFilter = $WmiFilter
        
        }   #End of $Properties...
       
        #Add our new object to an array
        [Array]$TotalGPOs += $GpoInfo

    }   #End of ForEach ($Backup in $Backups)...

    #####################
    ##BACKUP WMI FILTERS
    #Connect to the Active Directory to get details of the WMI filters
    $WmiFilters = Get-ADObject -Filter 'objectClass -eq "msWMI-Som"' `
                               -Properties msWMI-Author, msWMI-ID, msWMI-Name, msWMI-Parm1, msWMI-Parm2 `
                               -ErrorAction SilentlyContinue

    ######################
    ##CREATE REPORT FILES
    ##XML reports
    #Create a variable for the XML file representing custom information about the backed up GPOs
    $CustomGpoXML = "$SubBackupFolder\GpoDetails.xml"

    #Export our array of custom GPO objects to XML so they can be easily re-imported as objects
    $TotalGPOs | Export-Clixml -Path $CustomGpoXML

    #If $WMIFilters contains objects write these to an XML file
    If ($WmiFilters) {

        #Create a variable for the XML file representing the WMI filters
        $WmiXML = "$SubBackupFolder\WmiFilters.xml"

        #Export our array of WMI filters to XML so they can be easily re-imported as objects
        $WmiFilters | Export-Clixml -Path $WmiXML

    }   #End of If ($WmiFilters)

    ##CSV report
    #Create a variable for the CSV file that will contain the SOM (Scope of Management) information for each backed-up GPO
    $SOMReportCSV = "$SubBackupFolder\GpoInformation.csv"

    #Now, let's create the CSV report 
    ForEach ($CustomGPO in $TotalGPOs) {
        #Start constructing the CSV file line entry for the current GPO
        $CSVLine = "`"$($CustomGPO.Name)`",`"{$($CustomGPO.GPOGuid)}`","

        #Expand the SOMs property of the current object
        $CustomSOMs = $CustomGPO.SOMs

        #Loop through any SOMs returned
        ForEach ($CustomSOM in $CustomSOMs) {
            #Append the SOM path to our CSV line
            $CSVLine += "`"$CustomSOM`","
        }   #End of ForEach ($CustomSOM in $CustomSOMs)...

       #Write the newly constructed CSV line to the report
       Add-Content -Path $SOMReportCSV -Value $CSVLine
    }   #End of ForEach ($CustomGPO in $TotalGPOs)...

    ###########
    ##MIGTABLE
    #Check whether a migration table should be created
    If ($MigTable) {
        #Create a variable for the migration table
        $MigrationFile = "$SubBackupFolder\MigrationTable.migtable"

        #Create a migration table 
        $MigrationTable = $GPM.CreateMigrationTable()

        #Connect to the backup directory
        $GpmBackupDir = $GPM.GetBackUpDir($SubBackupFolder)

        #Reset the GPM search criterea
        $GpmSearchCriteria = $GPM.CreateSearchCriteria()

        #Configure search critera for the most recent backup
        $GpmSearchCriteria.Add($Constants.SearchPropertyBackupMostRecent,$Constants.SearchOpEquals,$True)

        #Get GPO information
        $BackedUpGPOs = $GpmBackupDir.SearchBackups($GpmSearchCriteria)

        #Add the information to our migration table
        ForEach ($BackedUpGPO in $BackedUpGPOs) {
            $MigrationTable.Add($Constants.ProcessSecurity,$BackedUpGPO)
        }   #End of ForEach ($BackedUpGPO in $BackedUpGPOs)...

        #Save the migration table
        $MigrationTable.Save($MigrationFile)
    }   #End of If ($MigTable)...
}   #End of If (Test-Path $SubBackupFolder)...

Open in new window

0

Join & Write a Comment

"Migrate" an SMTP relay receive connector to a new server using info from an old server.
This article will help you understand what HashTables are and how to use them in PowerShell.
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now