On Windows PowerShell and other admin-related topics

How to configure AntiAffinityClassNames in Failover Clustering using Windows PowerShell

AntiAffinityClassNames is a cluster group property in Windows Failover Clustering used to identify cluster groups that should not be hosted on the same node. When working with clustered Hyper-V environments there is a 1:1 relationship between a cluster group and a virtual machine, and thus we can configure Anti-Affinity for virtual machines using the AntiAffinityClassNames property. For more information, see the links in the resource section in the bottom of the article.

What I want to show in this article is how to configure the AntiAffinityClassNames property using PowerShell. Most articles I have seen in regards to AntiAffinityClassNames covers how to use cluster.exe to configure the property, and since the cluster.exe was deprecated in Windows Server 2008 R2 (it`s still available as a deprecated command) it might be a good idea to learn how to configure this using the new Failover Clustering PowerShell module. In addition you also get other benefits available in PowerShell such as pipelining, export/import to/from different data sources, grouping and so on.

AntiAffinityClassNames is a property of a cluster group, but before we configure the property we need to look at what type it is. We can do this by piping the output of Get-ClusterGroup to the Get-Member cmdlet:


We can see in the definition of the property that it is a System.Collections.Specialized.StringCollection type. This means we can not just pass a text string as the property value, we need to create a object of the correct type. The reason this property is not just a System.String (text string) is that a Cluster Group can have more than one AntiAffinityClassNames values. System.Collections.Specialized.StringCollection has a method called Add which can be used to to add values to the collection. Here is a complete example on how to create such an object, add a couple of values to it and at the end assign it to the AntiAffinityClassNames property of a cluster group:

$value = New-Object System.Collections.Specialized.StringCollection
$value.Add("Domain Controllers")
$value.Add("Infrastructure Server Group")
(Get-ClusterGroup "SCVMM SRV01 Resources").AntiAffinityClassNames = $value

Note that this will overwrite any existing values. As we can see it is not very hard to configure a new value, but it might be harder if you want to preserve existing values remove single items of the existing value and so on. In order to make this easier I have created a PowerShell module which contains 3 script cmdlets for managing AntiAffinityClassNames:


As you can see in the cmdlet help there is support for pipeline input, which makes it possible to configure the AntiAffinityClassNames values based on input such as a CSV-file:


I have also provided examples for the script cmdlets:



Installing the AntiAffinityClassNames module

Download and unzip in the following location: %userprofile%\Documents\WindowsPowerShell\Modules\AntiAffinityClassNames

Alternatively you may save the module in any of the folders in the $Env:PSMODULEPATH variable or import the module from a custom path (Import-Module <path>\AntiAffinityClassNames). Here is some more examples to get you started:

# Import the module
Import-Module AntiAffinityClassNames

# Example usage of the Get-AntiAffinityClassNames script cmdlet

Get-AntiAffinityClassNames -Cluster cluster01.domain.local

Get-AntiAffinityClassNames -Cluster cluster01.domain.local -ClusterGroup "SC VMM SRV01 Resources"

Get-AntiAffinityClassNames -Cluster cluster01.domain.local | Export-Csv -Path c:\temp\AntiAffinityClassNames_cluster01.csv -NoTypeInformation

# Example usage of the Set-AntiAffinityClassNames script cmdlet

Set-AntiAffinityClassNames -Cluster cluster01.domain.local -ClusterGroup "SC VMM SRV01 Resources" -Value "Domain Controllers"

Set-AntiAffinityClassNames -Cluster cluster01.domain.local -ClusterGroup "SC VMM SRV01 Resources" -Value "Domain Controllers" -Keep

Set-AntiAffinityClassNames -Cluster cluster01.domain.local -ClusterGroup "SC VMM SRV01 Resources" -Value "Domain Controllers" -Verbose

# Example usage of the Remove-AntiAffinityClassNames script cmdlet

Remove-AntiAffinityClassNames -Cluster cluster01.domain.local -ClusterGroup "SC VMM SRV01 Resources" -Clear

Remove-AntiAffinityClassNames -Cluster cluster01.domain.local -ClusterGroup "SC VMM SRV01 Resources" -Value "Domain Controllers"

Remove-AntiAffinityClassNames -Cluster cluster01.domain.local -ClusterGroup "SC VMM SRV01 Resources" -Value "Domain Controllers" -Verbose



MSDN: AntiAffinityClassNames

Failover behavior on clusters of three or more nodes

Understanding Hyper-V Virtual Machine (VM) Failover Policies

Private Cloud: Configuring anti-affinity between VMs on Hyper-V 2008 R2 SP1 and VMM 2012

How to automatically avoid running Exchange VMs on the same Hyper-V server after a host failure

Get started with the Failover Clustering PowerShell-module

Enable Persistent Mode for Cluster Resource Groups using the PowerShell Failover Clustering module

February 23, 2012 Posted by | Failover Clustering, Hyper-V R2, Virtualization, Windows PowerShell, Windows Server 2008 R2 | , | Leave a comment

Adding printer drivers from a print server using Windows PowerShell

Managing printer drivers in a Remote Desktop Services (formerly Terminal Services) environment can be a challenge for administrators. There are many ways to ease this challenge, including third party solutions such as ThinPrint and UniPrint. When “thick” drivers are used on the RDS servers, all printer drivers must be installed locally on every server. Citrix XenApp has a printer driver replication feature which makes it possible to distribute printer drivers from a source server to one or more destination servers in a farm.

There might be situations where none of the mentioned solutions can be used for various reason, i.e. financial costs. A common way to solve this problem is to map all printer connections from a specified print server using administrative credentials during the initial setup of each RDS server. This solves the problem, but it can be time consuming as all printers that uses the same driver is being installed. Even though the driver is already installed on the local computer, it takes some time to process each printer connection.

I recently faced this challenge, as the installation of all printer connections from a few specified print servers took 30-40 minutes using a legacy script. I then wrote an advanced function in PowerShell to make the procedure more effective. This was accomplished by installing a printer connection only for unique printer drivers.
An example: A print server has 500 shared printer objects, while there is only 10 unique printer drivers. It would make more sense to add a printer connection (in order to install the driver) to 10 printer objects rather than 500, given the time consumed by installing a printer connection.

The function is available for download from here.

Sample usage and output:




There is a switch option added to the function called Clean. If this parameter is specified the function will also remove all mapped printer connections for the current user.

The function doesn’t`t provide any log options. However, it produces PowerShell objects, so it would be easy to pipe the output to a file.
An example on how to export the output objects to a csv-file:


But what about printer drivers added to the print servers after the function is run on an RDS server? One way to solve this could be adding the PowerShell function to a script-file which is set up as a scheduled task to run i.e. once a day on every RDS server.  If the scheduled task is set up using Group Policy Preferences, it will be automatically created on every new RDS server that is added later on. Beside scheduling the task to run at specified intervals, the print server administrator may also invoke the scheduled task remotely on every RDS server whenever a new print driver is added to a print server. The details on how to do this is previously described in this blog-post.

Since the function might be run several times on the same computer, it also checks if the driver to be installed is already in place on the local computer. This means that after the first run, only printer drivers added to the print server after the first run is actually installed. This makes the script more effective, and depending on the number of shared printer objects on the specified print server, it shouldn’t`t run for many seconds.

Coming back to the before mentioned example (~600 printer objects, ~50 unique drivers) where it took 30-40 minutes to install printer drivers from a print server, when using the Add-PrinterDriver PowerShell function the execution ran for 4 minutes. After the first run, subsequent executions ran for  20 seconds.

July 3, 2011 Posted by | Print management, Remote Desktop Services, Scripting, Terminal Services, Windows PowerShell, Windows Server 2008, Windows Server 2008 R2 | , , , , | 5 Comments

Enable Persistent Mode for Cluster Resource Groups using the PowerShell Failover Clustering module

In Failover Clustering in Windows Server 2008 R2, Persistent Mode is intended to allow resource groups to come online on the node which an admin last moved them to. This setting is enabled by default when a virtual machine is created with Failover Cluster Manager. If you create virtual machine via System Center Virtual Manager this setting is not enabled.

By default, cluster roles have this setting disabled, except for Hyper-V virtual machine cluster roles, which have this enabled by default. This setting is useful when the cluster is shutdown and later started, in order to better distribute the resources across the nodes and allow them to come online faster, as they were likely spread across the nodes before the cluster was offlined. Otherwise, all the resources will attempt to restart on the first nodes which achieve quorum and compete for resources. This only applies to a group if it did not failover after being placed by the administrator. If a group has failed over since the last administrator placement, it is brought online on the node which the administrator last move it to.

Reference and more info regarding the Auto Start, Persistent Mode and Group Wait Delay features is available on the Clustering and High-Availability blog.

Auto Start can be enabled/disabled in bulk by marking all Cluster Resource Groups in Failover Cluster Manager and selecting “Enable auto start”/”Disable auto start”.

For Persistent Mode the only available option in Failover Cluster Manager is to right click each Cluster Resource Group and selecting/de-selecting the checkbox for “Enable persistent mode”:


To change this setting for all Cluster Resource Groups in an automated fashion you can use the Failover Cluster module for PowerShell, which I wrote an introduction to here.

Here is an example on how you can do this:

Import-Module FailoverClusters
$clustergroups = Get-ClusterGroup -Cluster cluster01.domain.local
foreach ($clustergroup in $clustergroups) {
#To enable persistent mode: x To disable persistent mode: 4294967295

Although you can change the Auto Start setting in bulk in Failover Cluster Manager you might also want to do this in an automated fashion:

Import-Module FailoverClusters
$clustergroups = Get-ClusterGroup -Cluster cluster01.domain.local
foreach ($clustergroup in $clustergroups) {
#To enable Auto Start: 1 To disable Auto Start: 0

You can also change the Group Wait Delay cluster-wide property from the PowerShell Failover Clustering module, how to do this is explained in the above referenced blog-post from the Clustering and High-Availability blog.

For the next version of System Center Virtual Machine Manager I would expect that Persistent Mode is enabled by default, since Microsoft do recommend customers to enable this setting.

Update 08.12.2011: The value of the DefaultOwner property for configuring Persistent Mode is the number of the node you want to be the default owner. In example a value of 1 means the first node in the cluster.

June 3, 2011 Posted by | Failover Clustering, Hyper-V, Hyper-V R2, Scripting, Windows PowerShell, Windows Server 2008 R2 | , | 3 Comments

Administering Active Directory Rights Management Services using Windows PowerShell

Starting with Windows Server 2008 R2, Active Directory Rights Management Services (AD RMS) can be installed and administered using Windows PowerShell.
The PowerShell support in AD RMS is divided into two PowerShell modules:

  • ADRMS – Deployment module
  • ADRMSAdmin – Administration module

On a Windows Server 2008 R2 server with the AD RMS server role installed we can see the modules using Get-Module –ListAvailable:



The AD RMS configuration is exposed through a PowerShell Provider, which we can see using Get-PSProvider after the RMS-modules are imported:


Before we can use any of the cmdlets exposed through the AD RMS modules we need to create a PSDrive using the AD RMS PowerShell Providers. In the following example we`re creating a new PSDrive for the AD RMS Administration module, where we specify the PSProvider to use as well as the URL to the AD RMS cluster:


When a PSDrive is set up we can navigate to the PSDrive using cd (alias for Set-Location), and access the different configuration properties. The available containers we can see are similar to what is available in the Graphical User Interface for managing AD RMS:


As an example we can we and edit the SuperUser configuration:



Next we can have a look at the available cmdlets in the AD RMS Administration module by using Get-Command –Module ADRMSAdmin:


Note that 5 new cmdlets was added to the AD RMS Administration module in Windows Server 2008 R2 SP1, due to added functionality to support Microsoft Federation Gateway.

Let`s try the Get-RmsSystemHealth cmdlet:


Notice that the –Path parameter is required, and needs to be pointed at the PSDrive we created earlier.

The same concepts as we`ve looked at for the AD RMS Administration module is the same for the AD RMS Deployment module:


We need to create a PSDrive where the AD RMS Cluster configuration are set before we can use the three cmdlets available for installing, uninstalling or updating the AD RMS deployment.


For further reference, the AD RMS PowerShell support are well documented on Microsoft TechNet:

Using Windows PowerShell to Deploy AD RMS

AD RMS Deployment Cmdlets

Using Windows PowerShell to Administer AD RMS

AD RMS Administration Cmdlets

Active Directory Rights Management Services on Windows Server TechCenter

April 10, 2011 Posted by | Active Directory Rights Management Services, Windows PowerShell, Windows Server 2008 R2 | , | Leave a comment

DFS-R Health Report for SYSVOL

Distributed File System Replication (DFS-R) was introduced as a replacement for File Replication Service (FRS) in Windows Server 2008, and was further enhanced in Windows Server 2008 R2. When your domain functional level are set to Windows Server 2008, you have the option to migrate SYSVOL-replication from the deprecated FRS to the new and more reliable DFS-R service. A major advantage of using DFS-R over FRS is that FRS copies the whole file when a change are made, while DFS-R only copies the changed bits. This and further details are discussed here. I`ve also included some links in the resource section below on how to perform an FRS to DFS-R migration.

Included in the Windows Server 2008 and Windows Server 2008 R2 are the DFS Management-console as well as several command-line tools for administering DFS. A great built-in feature in these tools is the diagnostic reports.

This is available in the DFS Management-console:


As well as from the DfsrAdmin.exe command-line tool:


Using this feature we can generate an HTML-report containing a great overview of the replication health for the SYSVOL replication group:


Any errors and warnings will be shown with detailed explanations. In addition we can view general information and statistics i.e. regarding free diskspace on the domain controllers, bandwith savings and so on (click on the thumbnail to view):


Since the reporting feature are available from the DfsrAdmin.exe command-line tool, it makes it easy to set up a script as a scheduled task that also sends the generated report via e-mail i.e. every morning. I`ve published a simple PowerShell-script to accomplish this which is available here.


SYSVOL Replication Migration Guide: FRS to DFS Replication (Word-version available here)

Verifying File Replication during the Windows Server 2008 DFSR SYSVOL Migration


Configuring DFSR to a Static Port

FRS to DFSR Migration Tool (not for SYSVOL migration)

December 30, 2010 Posted by | Active Directory management, DFS-R, Scripting, Windows PowerShell, Windows Server 2008, Windows Server 2008 R2 | | 2 Comments

Get started with the Failover Clustering PowerShell-module

In Windows Server 2008 R2 the Failover Clustering feature contains a Windows PowerShell-module for administering Failover Clusters. This module replaces the old cluster.exe tool which existed in previous versions of Windows Server.

The cmdlets in the Failover Clustering module for PowerShell are well documented on Microsoft TechNet: “Using Windows PowerShell Cmdlets on Failover Clusters in Windows Server 2008 R2”.

There is also a guide on “Mapping Cluster.exe Commands to Windows PowerShell Cmdlets for Failover Clusters”, which a member of the File Server team at Microsoft, Jose Barreto, has posted additional details on in a blog-post.

I recently created two new Failover Cluster for Hyper-V, and leveraged the Failover Clustering PowerShell module. Here is a sample on how easy it is to accomplish this:




























#Import Server Manager module

Import-Module ServerManager 

# Add Failover Cluster and Hyper-V (requires a reboot)

Add-WindowsFeature “Failover-Clustering”,“Hyper-V”

#Configure networks in Hyper-V before moving on

#Import Failover Clustering module

Import-Module FailoverClusters

#Create cluster validation report

Test-Cluster -Node Node01,Node02

#Inspect cluster validation report before moving on

#Create a new failover cluster

New-Cluster -Name Cluster01 -Node Node01,Node02 -StaticAddress

#Inspect available cluster disks

Get-ClusterAvailableDisk -Cluster Cluster01

#Add all available cluster disks

Get-ClusterAvailableDisk -Cluster Cluster01 | Add-ClusterDisk

#Configure cluster quorom

Set-ClusterQuorum -Cluster Cluster01 -NodeAndDiskMajority “Cluster Disk 01”

#Enable Cluster Shared Volumes

(Get-Cluster -Name Cluster01).EnableSharedVolumes=“Enable/NoticeRead”

#Add Cluster Shared Volume

Add-ClusterSharedVolume -Cluster Cluster01 -Name “Cluster Disk 02”

#Make VM 01 Highly Available

Add-ClusterVirtualMachineRole -Cluster Cluster01 -VirtualMachine “VM 01” -Name “VM 01”

#Test cluster failover on VM 01

Move-ClusterVirtualMachineRole -Cluster Cluster01 “VM 01” -Node Node02

Before running the commands in the example above, you must install the operating system and configure disks and networking for Failover Clusters according to the product documentation on Microsoft TechNet. If you are using a Windows Server 2008 R2 Core edition, the Core Configurator 2.0 might be handy if you`re not comfortable configuring IP-addresses and so on from the command line.

Additional resources

Failover Clustering and Network Load Balancing Team Blog

Cluster Related Sessions at TechEd Berlin 2010

Joachim Nässlander (Cluster MVP)

John Toner (Cluster MVP)

November 28, 2010 Posted by | Failover Clustering, Windows PowerShell, Windows Server 2008 R2 | | 4 Comments

Starting an RemoteApp through RD Web Access and RD Gateway fails with “The logon attempt failed”

In Windows Server 2008 R2, it`s possible to use RD Web Access and RD Gateway for starting RemoteApp applications, using Single Sign-On (SSO).
The Remote Desktop Services Team has a great article here on how to configure this setup.

While troubleshooting a problem with the SSO-feature lately, we got an error message saying “The logon attempt failed”.

The solution turned out to be rather simple. While the default logon page for RD Web Access indicates “Domain/user name” for the user name field, using only the user name works fine:



This works fine as long as your not using RD Gateway and SSO, then the error message mentioned will occur when trying to start a RemoteApp.
When RD Gateway and SSO are being used, you must supply the domain as part of the user name (domain\ user name), else the SSO-feature will break.

I actually contacted Microsoft to clarify if it is possible to hardcode the domain name some way, and got the following answer:

I have taken time to discuss with our develop team. Please understand that there is no easy way to finish the task, because in RemoteApp mode RDP client ignores user name and domain name. We need to put a domain hint on the RD Web page. It is related to coding and design. If you want to request a feature or code change, you also can contact our Advisory Service by using the contact info published at <>.

Hopefully this will be possible in future Service Packs or OS releases.

September 17, 2010 Posted by | Remote Desktop Services, Windows Server 2008 R2 | , | 2 Comments

Invoke Best Practices Analyzer on remote servers using PowerShell

Best Practices Analyzer (BPA) is a management tool integrated in Windows Server 2008 R2 used to scan server roles according to Microsoft best practice guidelines.

Included in the initial release for Windows Server 2008 R2 are the following BPA models:

  • Active Directory Domain Services
  • Active Directory Certificate Services
  • Domain Name System (DNS) Server
  • Remote Desktop Services
  • Web Server (IIS)

Since then several new BPA models are released and available both as separate downloads as well as through Windows Update:

At the time of this writing, a BPA model for 12 of 17 server roles in Windows Server 2008 R2 are available.
The 5 that are not available are:

  • Active Directory Federation Services (ADFS)
  • Active Directory Lightweight Directory Services (AD LDS)
  • Fax Server
  • Print and Document Services
  • Windows Deployment Services

In Server Manager, a BPA summary are available for each installed server role that an BPA Model exists for:


When looking at the properties for an item in BPA you get more information as well as a link to Microsoft TechNet where more information are available for the specific subject:


BPA are built as a PowerShell module, meaning that a PowerShell cmdlet (Invoke-BPAModel) are run in the background when you scan a server role from Server Manager:


This is a great feature to examine if your server roles are configured according to Microsoft`s best practices, however, if you got many servers it will take some time to log on to each server and scan each server role. In addition you don`t get any centralized reporting this way.

Since BPA are based upon Windows PowerShell it`s possible to solve this using the BPA PowerShell module and PowerShell remoting:



I`ve created a sample script to accomplish this, named Invoke-BPAModeling, with the following functionality:

  • Invoke BPA for all available server roles on specified remote servers
  • E-mail reporting
  • File reporting to CSV and HTML

You need to customize the initial variables on the top of the script. You can enable/disable reporting using these variables, as well as specify which servers to work against, SMTP server for e-mail reporting and paths to CSV/HTML reports.
By default, only items with a severity of “Error” and “Warning” are reported. You can change this to also include “Informational” severities by configuring IncludeAllSeverities to true.
On the server running the script from, the Active Directory module for PowerShell must be installed if you want to retrieve computer names from Active Directory. In the sample,  the script are configured to retrieve all computer accounts listed with Windows Server 2008 R2 as operating system.
You might choose alternate methods, like importing the computer names from a csv-file.
I would recommend that you approve the new BPA models mentioned at the beginning of this blog post in WSUS prior to running the script.
The script requires that PowerShell remoting are enabled and configured on the remote servers. Also note that there is a known issue with the BPA module; When the PowerShell execution policy are set to any other than “Undefined” or “Unrestricted” , an error occurs. I`ll update this blog-post as soon as a fix are provided from Microsoft.

When the script executes, it displays the progress based upon the total number of computers running against:


Sample e-mail report containing both CSV and HTML reports as attachment:


Sample HTML-report:


Sample CSV-report converted to an Excel spreadsheet:


Feel free to customize the script for your needs, as well as suggest improvements.


Best Practices Analyzer on Microsoft TechNet

August 17, 2010 Posted by | Best Practices, Scripting, Windows PowerShell, Windows Server 2008 R2 | | 4 Comments

Manage RDS RemoteApp with Windows PowerShell

In Windows Server 2008 R2, Remote Desktop Services (formerly Terminal Services) includes a provider for managing RDS using Windows PowerShell. You may find more information along with some examples in this article on Microsoft TechNet.

One of the many things you can manage this way is the new RemoteApp-feature introduced with Windows Server 2008. In Windows Server 2008 R2, this feature got enhanced by the addition of User Assignment and Web Single Sign-On capabilities. These new features makes it possible for more and more customers to consider RDS without additional products like Citrix. One benefit using Citrix are more flexible application-management, since an published application may be available from a new farm member without adding each application manually.

Let`s look at a given example: You got a farm with 16 RDS-servers, and you`re leveraging the RemoteApp-feature. For each server in the farm, you must manually set up all applications in RemoteApp-manager after they`re installed. Although there is an export/import-feature in the GUI, many customers require no manual interaction in the server provisioning process. By the addition of the new PowerShell-provider for RDS, this is now possible in RemoteApp using scripting as part of either server provisioning or Group Policy.

For the average Windows sysadmin, I imagine that managing RemoteApp using the RDS PowerShell provider might be a bit tedious. To make this a little easier I`ve created a Windows PowerShell module for working with RDS RemoteApp, available from here.

This module contains the following functions:

  • Get-RDSRemoteApp
  • Export-RDSRemoteApps
  • Import-RDSRemoteApps
  • New-RDSRemoteApp
  • Remove-RDSRemoteApp

The functions let you administer the same application attributes as the graphical RemoteApp Manager:

  • Displayname
  • Alias
  • Command-line arguments
  • RD Web Access availability
  • User Assignment


Installing the RDSRemoteApp module

Download and unzip in the following location: %userprofile%\Documents\WindowsPowerShell\Modules\RDSRemoteApp

Alternatively you may save the module in any of the folders in the $Env:PSMODULEPATH variable.

Using the RDSRemoteApp module

First we`ll have a look at the RemoteApp Manager application-list in the lab-environment:


Start Windows PowerShell on the RDS-server and import the module (you will need to run PowerShell with Administrative privileges):


Since I`ve leveraged the built-in help capabilities in Windows PowerShell v2 Advanced Functions, I`ll show the usage of the functions with a few screenshots from the help:











Sample usage for export/import:


Be aware that there are several other RDS settings that may be managed using the PowerShell provider, this module only leverages the RemoteApp functionality. If someone want to create a module for managing other aspects of RDS, feel free to include my RDSRemoteApp module. And as always, suggestions for improvements and new functionality are more than welcome.

June 30, 2010 Posted by | Deployment, Remote Desktop Services, Scripting, Terminal Services, Windows PowerShell, Windows Server 2008 R2 | | 3 Comments

Backing up Group Policy Objects using Windows PowerShell

A best practice in domain environments are backing up the Group Policy Objects regularly. Even though a GPO may be restored by restoring a system state backup from a domain controller to an alternate location, and then copy the contents from the deleted GPO to a new GPO to restore the settings, this may be a hazzle since it`s not pretty straightforward. It also requires you to restart the domain controller affected in Directory Services Restore Mode.
PowerShell MVP Don Jones has written a good article on this topic, available here.

For those of you who may not want to do GPO restore the hard way, or buy a commercial third party product, I would encourage you to schedule regular GPO backups using the Windows PowerShell Group Policy-module available in Windows Server 2008 R2, as well as RSAT in Windows 7.
To accomplish this, I`ve written a small script which backs up all modified GPO`s in the specified timespan. I would generally recommend to have the script run once a day, thereby setting the timespan-variable to the last 24 hours. The script are called Backup-ModifiedGPOs.ps1, and available from here.

All Group Policy Objects modified in the specified timespan are backup up to the specified backup path.
Also, an HTML-report are created for each GPO-backup, with the unique backup GUID as part of the filename. This way you can easily see what settings each backup contains.

When restoring a GPO, you must first note the GUID of the backup you want to restore. Then you can restore the GPO by using the Restore-GPO cmdlet in the Group Policy-module. Sample usage:


Administrators who feels more comfortable working with the GUI, may use the Group Policy Management Console to do the restore.

The following procedure from the Group Policy Planning and Deployment Guide on Microsoft TechNet describes how to accomplish the restore operation from the GUI:

To view the list of GPO backups

  1. In the GPMC console tree, expand the forest or domain that contains the GPOs that you want to back up.
  2. Right-click Group Policy Objects, and the click Manage Backups.
  3. In the Manage Backups dialog box, enter the path to the location where you stored the GPO backups that you want to view. Alternatively, you can click Browse, locate the folder that contains the GPO backups, and then click OK.
  4. To specify that only the most recent version of the GPOs be displayed in the Backed up GPOs list, select the Show only the latest version of each GPO check box. Click Close.

Using the GPMC to restore GPOs

You can also restore GPOs. This operation restores a backed-up GPO to the same domain from which it was backed up. You cannot restore a GPO from a backup into a domain that is different from the GPO’s original domain.

To restore a previous version of an existing GPO

  1. In the GPMC console tree, expand Group Policy Objects in the forest or domain that contains the GPOs that you want to restore.
  2. Right-click the GPO that you want to restore to a previous version, and then click Restore from Backup.
  3. When the Restore Group Policy Object Wizard opens, follow the instructions in the wizard, and then click Finish.
  4. After the restore operation completes, a summary will state whether the restore succeeded. Click OK.

To restore a deleted GPO

  1. In the GPMC console tree, expand the forest or domain that contains the GPO that you want to restore.
  2. Right-click Group Policy Objects, and then click Manage Backups.
  3. In the Manage Backups dialog box, click Browse, and then locate the file that contains your backed-up GPOs.
  4. In the Backed up GPOs list, click the GPO that you want to restore, and then click Restore.
  5. When you are prompted to confirm the restore operation, click OK.
  6. After the restore operation completes, a summary will state whether the restore succeeded. Click OK. Click Close.

Important: Since Group Policy links are stored on the Organizational Unit objects in Active Directory, this information are not backup up and also not restore. However, the HTML backup-reports contains this information, so you may manually re-link the GPO to the correct OU(s).

Also note that WMI filters and IPSec policies are not backed up by the backup feature in the Group Policy Management Console. For more information on how to manage these items, see the before mentioned Group Policy Planning and Deployment Guide.


June 15, 2010 Posted by | Active Directory management, Group Policy, Scripting, Windows 7, Windows PowerShell, Windows Server 2008 R2 | 12 Comments