{"id":17751,"date":"2010-07-15T00:01:00","date_gmt":"2010-07-15T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2010\/07\/15\/hey-scripting-guy-how-can-i-connect-two-group-policy-objects-in-active-directory-and-compare-them-offline-part-1\/"},"modified":"2010-07-15T00:01:00","modified_gmt":"2010-07-15T00:01:00","slug":"hey-scripting-guy-how-can-i-connect-two-group-policy-objects-in-active-directory-and-compare-them-offline-part-1","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-connect-two-group-policy-objects-in-active-directory-and-compare-them-offline-part-1\/","title":{"rendered":"Hey, Scripting Guy! How Can I Connect Two Group Policy Objects in Active Directory and Compare Them Offline? (Part 1)"},"content":{"rendered":"<p>&nbsp;<\/p>\n<p><img decoding=\"async\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\" \/><\/p>\n<p>Hey, Scripting Guy! I need to be able to connect to two <a href=\"http:\/\/technet.microsoft.com\/en-us\/windowsserver\/bb310732.aspx\">Group Policy<\/a> objects (GPOs) in <a href=\"http:\/\/gallery.technet.microsoft.com\/ScriptCenter\/en-us\/site\/search?f%5B0%5D.Type=RootCategory&amp;f%5B0%5D.Value=activedirectory&amp;f%5B0%5D.Text=Active%20Directory\">Active Directory<\/a> and make an offline copy of the GPOs using <a href=\"http:\/\/support.microsoft.com\/kb\/968929\">Windows PowerShell 2.0<\/a> so that I can compare the two objects. I know I can do this using the Group Policy Management Console, but I have several hundred GPOs in my domain and I do not have the time to go through the GUI and click-click-click. I would prefer to be able to script this operation using Windows PowerShell, if possible. Ideas?<\/p>\n<p>&#8212; SV<\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\" \/><\/p>\n<p>Hello SV, <\/p>\n<p>Microsoft Scripting Guy Ed Wilson here. One of the cool things about Windows PowerShell is that when one thing does not work, often a different approach can be taken that will work. Such was my experience this week while trying to answer your question. There are many graphical tools available that will allow you to compare two XML files. One such tool is <a href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?familyid=72d6aa49-787d-4118-ba5f-4f30fe913628&amp;displaylang=en\">XML Notepad<\/a>, which is free from Microsoft. But there are relatively few programmatic tools one can use. When searching MSDN, I came across a really old package called the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa302294.aspx\">XML Diff and Patch Tool<\/a> that looks like it might be fun. The problem is that, when attempting to install it on <a href=\"http:\/\/www.microsoft.com\/windows\/windows-7\/default.aspx\">Windows 7<\/a>, it complains the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/netframework\/aa569264.aspx\">.NET Framework 1.1<\/a> is not installed; I did not feel like downloading, installing, and patching a six-year-old version of the .NET Framework. <\/p>\n<blockquote>\n<p><strong>Note<\/strong>: This is part one of a two-part article. Part two will be posted tomorrow.<\/p>\n<\/blockquote>\n<p>I then began to look at <a href=\"http:\/\/msdn.microsoft.com\/en-us\/netframework\/aa904594.aspx\">Language-Integrated Query<\/a> (<a href=\"http:\/\/msdn.microsoft.com\/en-us\/netframework\/aa904594.aspx\">LINQ<\/a>) and <a href=\"http:\/\/msdn.microsoft.com\/library\/bb308960.aspx\">LINQ to XML<\/a>. LINQ builds data query language capabilities directly into the programing language (such as <a href=\"http:\/\/www.microsoft.com\/express\/vcsharp\/Default.aspx\">C#<\/a> or <a href=\"http:\/\/www.microsoft.com\/express\/vb\/\">VB.Net<\/a>) and therefore it makes data query as easy as <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/guide\/sas_log_udqz.mspx\">querying<\/a> a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa394582(VS.85).aspx\">WMI<\/a> class in Windows PowerShell 2.0. While there are a number of LINQ .NET Framework classes that can be used in Windows PowerShell 2.0 in the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb299195.aspx\">System.XML.LINQ<\/a> .NET Framework namespace, the ability to use or to create a LINQ query does not appear. I guess I could have used the <strong>Add-Type<\/strong> trick and executed native C# code, but SV, I did not want to do that for your script if I could avoid it. In the end, I decided to use Windows PowerShell directly to perform this operation. <\/p>\n<p>SV, you can download all of the GPOs in your domain in a single command directly from the Windows PowerShell console. You will need to first import the Group Policy <a href=\"http:\/\/blogs.technet.com\/heyscriptingguy\/archive\/tags\/getting+started\/modules\/default.aspx\">module<\/a>. Then you can run your command as shown here: <\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #0000ff\">PS<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">C:\\&gt;<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">Import-Module<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">group<\/span><span style=\"color: #000000\">*<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #0000ff\">PS<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">C:\\&gt;<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">Get-GPOReport<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-All<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-Path<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">c:\\fso\\allgporeport.xml<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-ReportType<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">xml<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #0000ff\">PS<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">C:\\&gt;<\/span><span style=\"color: #808080\"> <br \/><\/span><\/div>\n<p>After the Group Policy report has been saved, it can be opened in XML Notepad and viewed, as shown in the following image.<\/p>\n<p><a href=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2010\/july\/hey0715\/hsg-07-15-10-01.jpg\"><img decoding=\"async\" style=\"border-bottom: 0px;border-left: 0px;border-top: 0px;border-right: 0px\" title=\"Image of viewing Group Policy report in XML Notepad\" border=\"0\" alt=\"Image of viewing Group Policy report in XML Notepad\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/0576.hsg071510011_0A51D662.jpg\" width=\"604\" height=\"446\" \/> <\/a><\/p>\n<p>SV, because you stated you wished to create offline representations of all your GPOs so that you would be able to more easily compare them to each other, I decided to create a small script to perform this operation. (The command could also be typed on a single line in the Windows PowerShell console. In fact, this is the way I developed the &ldquo;script.&rdquo;) The <a href=\"http:\/\/gallery.technet.microsoft.com\/ScriptCenter\/en-us\/98f56f49-c78e-4563-baa1-d39a53a41529\">Get-XMLForEachGPO.ps1 script<\/a> is shown just below. It begins by getting a list of all the GPOs in the domain, using the <strong>Get-GPO<\/strong> cmdlet. The returned objects are all instances of the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd537085(v=VS.85).aspx\">Microsoft.Grouppolicy.Gpo .NET Framework class<\/a>. The <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd536857(v=VS.85).aspx\">Microsoft.GroupPolicy namespace<\/a> contains a number of really cool classes that can be used from within Windows PowerShell scripts. The <a href=\"http:\/\/www.bing.com\/visualsearch?g=powershell_cmdlets&amp;FORM=Z9GE22\">ForEach-Object cmdlet<\/a> cmdlet is used in the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/winpsh\/manual\/pipe.mspx\">pipeline<\/a> to allow you to work with each GPO. The <strong>Join-Path<\/strong> cmdlet is used to create the path to store the outputted XML report. Inside the pipeline, the <strong>Get-GPOReport<\/strong> cmdlet obtains the XML report <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/ee198910.aspx\">for each<\/a> of the GPO objects. The Get-XMLForEachGPO.ps1 script is shown here. <\/p>\n<p><strong>Get-XMLForEachGPO.ps1<\/strong><\/p>\n<p><strong><\/strong><\/p>\n<div class=\"code\"><span style=\"color: #2b91af\">$path<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\"> &#8220;c:\\fso&#8221; <\/p>\n<p><\/span><span style=\"color: #000000\">get-gpo<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-All<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">|<\/span><span style=\"color: #808080\">&nbsp; <\/p>\n<p><\/span><span style=\"color: #0000ff\">ForEach-Object<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\">&nbsp; <\/p>\n<p><\/span><span style=\"color: #000000\">Get-GPOReport<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-Name<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$_<\/span><span style=\"color: #000000\">.displayname<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-ReportType<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">xml<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">`<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">-Path<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #0000ff\">join-path<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-Path<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$path<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-ChildPath<\/span><span style=\"color: #808080\"> &#8220;$($_.displayname).xml&#8221;<\/span><span style=\"color: #000000\">)<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">}<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>SV, I wrote a rather long script called Compare-GPO.ps1. I will talk about the first half of the script today and the second half of the script tomorrow. Because the complete script is so long (around 125 lines), I decided to upload it to the <a href=\"http:\/\/gallery.technet.microsoft.com\/ScriptCenter\/en-us\/18dea308-4faf-44bf-9e1c-e83d47edb866\">Scripting Guys Script Repository<\/a>. <\/p>\n<p>The Compare-GPO.ps1 script begins by creating several command-line parameters. The first is the domain name and the second is the server that you wish to contact in order to retrieve the GPOs. The <strong>$gponame<\/strong> variable holds a single string that contains the name of the two GPOs you wish to compare. As shown here, a comma separates the GPO names:<\/p>\n<p><span style=\"color: #000000\">[string]<\/span><span style=\"color: #2b91af\">$gponame<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\"> &#8220;aTestOuGPO,AnotherTestOuGPO&#8221;<\/span> <\/p>\n<p>The GPO name you use is the one shown in the Group Policy Management Console in the following image.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5873.hsg071510021_2D9ECB07.jpg\"><img decoding=\"async\" style=\"border-bottom: 0px;border-left: 0px;border-top: 0px;border-right: 0px\" title=\"Image of GPO name in GPMC\" border=\"0\" alt=\"Image of GPO name in GPMC\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2727.hsg071510021_thumb_741BBB0F.jpg\" width=\"604\" height=\"422\" \/><\/a> <\/p>\n<p>The folder parameter holds the destination for the GPOs. Two switched parameters, <strong>$computer<\/strong> and <strong>$user<\/strong>, are used to compare either the computer portion, the user portion, or both portions of the GPO. The command-line parameters are shown here:<\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #000000\">Param(<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">[string]<\/span><span style=\"color: #2b91af\">$domain<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&#8220;nwtraders.com&#8221;<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">[string]<\/span><span style=\"color: #2b91af\">$server<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\"> &#8220;dc1.nwtraders.com&#8221;<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">[string]<\/span><span style=\"color: #2b91af\">$gponame<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\"> &#8220;aTestOuGPO,AnotherTestOuGPO&#8221;<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">[string]<\/span><span style=\"color: #2b91af\">$folder<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\"> &#8220;c:\\fso&#8221;<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">[switch]<\/span><span style=\"color: #2b91af\">$user<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">[switch]<\/span><span style=\"color: #2b91af\">$computer<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">)<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>The first function that is added to the script is the <strong>Get-MyModule<\/strong> function that was discussed in a <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/tags\/weekend+scripter\/\">Weekend Scripter<\/a> article called <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2010\/07\/11\/hey-scripting-guy-weekend-scripter-checking-for-module-dependencies-in-windows-powershell.aspx\">Checking for Module Dependencies in Windows PowerShell<\/a>. The use of the <strong>Get-MyModule<\/strong> function to check for the <strong>GroupPolicy<\/strong> module is discussed in the Hey, Scripting Guy! Blog post, <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2010\/07\/12\/hey-scripting-guy-can-you-get-me-going-on-windows-powershell-cmdlets-for-group-policy.aspx\">Can You Get Me Going on Windows PowerShell Cmdlets for Group Policy?<\/a> The <strong>Get-MyModule<\/strong> function will therefore not be discussed here:<\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #000000\">Function<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">Get-MyModule<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">Param([string]<\/span><span style=\"color: #2b91af\">$name<\/span><span style=\"color: #000000\">)<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #0000ff\">if<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #0000ff\">-not<\/span><span style=\"color: #000000\">(Get-Module<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-name<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$name<\/span><span style=\"color: #000000\">))<\/span><span style=\"color: #808080\">&nbsp; <\/p>\n<p><\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\">&nbsp; <\/p>\n<p><\/span><span style=\"color: #0000ff\">if<\/span><span style=\"color: #000000\">(Get-Module<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-ListAvailable<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">|<\/span><span style=\"color: #808080\">&nbsp; <\/p>\n<p><\/span><span style=\"color: #0000ff\">Where-Object<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$_<\/span><span style=\"color: #000000\">.name<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">-eq<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$name<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">})<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\">&nbsp; <\/p>\n<p><\/span><span style=\"color: #000000\">Import-Module<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-Name<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$name<\/span><span style=\"color: #808080\">&nbsp; <\/p>\n<p><\/span><span style=\"color: #2b91af\">$true<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">}<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">#<\/span><span style=\"color: #000000\">end<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">if<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">module<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">available<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">then<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">import<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #0000ff\">else<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$false<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">}<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">#<\/span><span style=\"color: #000000\">module<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">not<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">available<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">}<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">#<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">end<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">if<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">not<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">module<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #0000ff\">else<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$true<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">}<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">#<\/span><span style=\"color: #000000\">module<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">already<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">loaded<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">}<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">#<\/span><span style=\"color: #000000\">end<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">function<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">get-MyModule<\/span><span style=\"color: #808080\"> <br \/><\/span><\/div>\n<p>You can modify the Get-XMLForEachGPO.ps1 script seen earlier to retrieve an XML report for the two specified GPOs, or you can use the <strong>Get-GPOAsXML<\/strong> function. The reason for the <strong>Get-GPOAsXML<\/strong> function is that it offers more flexibility than the Get-XMLForEachGPO.ps1 script. The <strong>Get-GPOAsXML<\/strong> function begins by defining the <strong>$gponame<\/strong> variable as an array of strings. When the script is called, the <strong>$gponame<\/strong> variable at the script level is a single string and is therefore not an array. However, when the <strong>Get-GPOAsXML<\/strong> function is called, the single string is split and therefore it becomes an array. The domain, server, and folder variables are the same as the ones from the beginning of the script. The <strong>Param<\/strong> section of the function is shown here:<\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #000000\">Function<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">Get-GPOAsXML<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">Param(<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">[string[]]<\/span><span style=\"color: #2b91af\">$gponame<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">[string]<\/span><span style=\"color: #2b91af\">$domain<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">[string]<\/span><span style=\"color: #2b91af\">$server<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">[string]<\/span><span style=\"color: #2b91af\">$folder<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">)<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>The <strong>$gpoReports<\/strong> variable is initialized and set to <strong>$null<\/strong>, and the <strong>ForEach<\/strong> statement is used to walk through the GPOs in the <strong>$gpoName<\/strong> variable, as shown here:<\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #2b91af\">$gpoReports<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$null<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #0000ff\">ForEach<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #2b91af\">$gpo<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">in<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$gpoName<\/span><span style=\"color: #000000\">)<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">{<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>Next, the <strong>Join-Path<\/strong> cmdlet is used to create a path to store the XML GPO report. The <strong>$gpo<\/strong> variable holds the name of the GPO that is currently being processed, and because an expanding string is used, the value in the <strong>$gpo<\/strong> variable will substitute for the variable itself to create a complete path. This is shown here:<\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #2b91af\">$path<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">Join-Path<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-Path<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$folder<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-ChildPath<\/span><span style=\"color: #808080\"> &#8220;$gpo.xml&#8221;<\/span> <\/div>\n<p>Next the <strong>Get-GPO<\/strong> cmdlet is used to retrieve an instance of the <strong>Microsoft.GroupPolicy.Gpo<\/strong> class. The <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/microsoft.grouppolicy.gpo.generatereporttofile(v=VS.85).aspx\">GenerateReportToFile method of the GPO class<\/a> is used to create the XML report:<\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #000000\">(Get-GPO<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-Name<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$gpo<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-Domain<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$domain<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-Server<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$server<\/span><span style=\"color: #000000\">).`<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">GenerateReportToFile(<\/span><span style=\"color: #808080\">&#8220;xml&#8221;<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #2b91af\">$path<\/span><span style=\"color: #000000\">)<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>An array of paths to the GPO reports is created and the array is passed back to the calling code. This is shown here: <\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #000000\">[array]<\/span><span style=\"color: #2b91af\">$gpoReports<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">+<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$path<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">}<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">Return<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$gpoReports<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">}<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">#<\/span><span style=\"color: #000000\">end<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">get-gpoasxml<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>SV, that is all there is to using Windows PowerShell to retrieve an XML representation of a Group Policy object. Group Policy Week will continue tomorrow when we will continue with the Compare-GPO.ps1 script and compare the two XML files. <\/p>\n<p>We would love for you to follow us on <a href=\"https:\/\/twitter.com\/scriptingguys\/\">Twitter<\/a> or <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send email to us at <a href=\"mailto:scripter@microsoft.com\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/social.technet.microsoft.com\/Forums\/en\/ITCG\/threads\/\">Official Scripting Guys Forum.<\/a> See you tomorrow. Until then, peace.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; Hey, Scripting Guy! I need to be able to connect to two Group Policy objects (GPOs) in Active Directory and make an offline copy of the GPOs using Windows PowerShell 2.0 so that I can compare the two objects. I know I can do this using the Group Policy Management Console, but I have [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[152,3,45],"class_list":["post-17751","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-group-policy","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>&nbsp; Hey, Scripting Guy! I need to be able to connect to two Group Policy objects (GPOs) in Active Directory and make an offline copy of the GPOs using Windows PowerShell 2.0 so that I can compare the two objects. I know I can do this using the Group Policy Management Console, but I have [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/17751","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=17751"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/17751\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=17751"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=17751"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=17751"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}