{"id":17741,"date":"2010-07-16T00:01:00","date_gmt":"2010-07-16T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2010\/07\/16\/hey-scripting-guy-how-can-i-connect-two-group-policy-objects-in-active-directory-and-compare-them-offline-part-2\/"},"modified":"2010-07-16T00:01:00","modified_gmt":"2010-07-16T00:01:00","slug":"hey-scripting-guy-how-can-i-connect-two-group-policy-objects-in-active-directory-and-compare-them-offline-part-2","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-2\/","title":{"rendered":"Hey, Scripting Guy! How Can I Connect Two Group Policy Objects in Active Directory and Compare Them Offline? (Part 2)"},"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. l am anxious to complete our discussion of the Compare-GPO.ps1 script. As you may recall, <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2010\/07\/15\/hey-scripting-guy-how-can-i-connect-two-group-policy-objects-in-active-directory-and-compare-them-offline.aspx\">yesterday<\/a> we looked at the portion of the script that determined if the <strong>GroupPolicy<\/strong> <a href=\"http:\/\/blogs.technet.com\/heyscriptingguy\/archive\/tags\/getting+started\/modules\/default.aspx\">module<\/a> was available and loaded, and we also looked at the function that downloaded the two GPOs to be compared. Because the <a href=\"http:\/\/gallery.technet.microsoft.com\/ScriptCenter\/en-us\/18dea308-4faf-44bf-9e1c-e83d47edb866\">Compare-GPO.ps1 script<\/a> is more than 125 lines long, I have posted it to our <a href=\"http:\/\/gallery.technet.microsoft.com\/ScriptCenter\/en-us\/f10e344a-ba60-40b8-89e0-01fdb262440f\">Script Repository<\/a> rather than pasting it into this post. <\/p>\n<blockquote>\n<p><strong>Note<\/strong>: This is part two of a two-part article. Part one was posted <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2010\/07\/15\/hey-scripting-guy-how-can-i-connect-two-group-policy-objects-in-active-directory-and-compare-them-offline.aspx\">yesterday<\/a>.<\/p>\n<\/blockquote>\n<p>The <strong>Compare-XMLGPO<\/strong> function is used to compare two XML reports of GPOs. It accepts an array of strings that point to the two XML files that will be used for comparison. It does not matter if more than two GPO reports are supplied because only the first two will be compared. The two Boolean values, <strong>$user<\/strong> and <strong>$computer<\/strong>, control which portion of the GPO is compared. If both values are present, both the computer and the user portion of the GPO will be compared. The <strong>[xml]<\/strong> type accelerator is used to ensure the contents of the two GPO reports are interpreted as XML. Reading the XML GPO reports is really easy&mdash;the <strong>Get-Content<\/strong> cmdlet is used. The <strong>$xml1<\/strong> and <strong>$xml2<\/strong> variables contain a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.xml.xmldocument.aspx\">system.xml.xmldocument<\/a> .NET Framework object. This section of the script 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\">Compare-XMLGPO<\/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\">$gpoReports<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">[bool]<\/span><span style=\"color: #2b91af\">$user<\/span><span style=\"color: #000000\">,<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">[bool]<\/span><span style=\"color: #2b91af\">$computer<\/span><span style=\"color: #000000\">)<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">[xml]<\/span><span style=\"color: #2b91af\">$xml1<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">Get-Content<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-Path<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$gpoReports<\/span><span style=\"color: #000000\">[<\/span><span style=\"color: #800000\">0<\/span><span style=\"color: #000000\">]<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">[xml]<\/span><span style=\"color: #2b91af\">$xml2<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">Get-Content<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-Path<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$gpoReports<\/span><span style=\"color: #000000\">[<\/span><span style=\"color: #800000\">1<\/span><span style=\"color: #000000\">]<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>To effectively parse the GPO XML report, you must know the structure of the XML document. I like to use <a href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?familyid=72d6aa49-787d-4118-ba5f-4f30fe913628&amp;displaylang=en\">XML Notepad<\/a>. As shown in the next image, the path to our GPO policy settings is GPO\/User\/extensiondata\/extension. Each policy setting is a node under the extension folder. This particular GPO setting is in an XML namespace (XMLNS) called q1. Therefore, each policy setting is in a node called q1:Policy. At times you will see an XML namespace called q2 or even something else. But each policy node will have the word <i>policy<\/i> in it. The breakdown between user and computer in the structure of the XML document corresponds with the Group Policy computer settings and user settings. <\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/0312.hsg071610011_7ADE327A.jpg\"><img decoding=\"async\" style=\"border-bottom: 0px;border-left: 0px;border-top: 0px;border-right: 0px\" title=\"Image of path to GPO policy settings\" border=\"0\" alt=\"Image of path to GPO policy settings\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7356.hsg071610011_thumb_0EF74F04.jpg\" width=\"604\" height=\"424\" \/><\/a> <\/p>\n<p>To compare the two GPOs, the <strong>childnodes<\/strong> property from the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/x97ek538.aspx\">System.Xml.XmlElement<\/a> .NET Framework class is used to obtain a collection of all the policy nodes under the <strong>extension<\/strong> element. There are many attributes associated with the <strong>policy<\/strong> element, but to make the comparison easier, only two attributes&mdash;the name and the state of the GPO&mdash;are selected. This selection is made for both the computer GPO and the user GPO from both XML documents. This section of the script is shown here: <\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #2b91af\">$regpolicyComputerNodes1<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$xml1<\/span><span style=\"color: #000000\">.gpo.Computer.extensiondata.extension.ChildNodes<\/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\">Select-Object<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">name,<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">state<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #2b91af\">$regpolicyComputerNodes2<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$xml2<\/span><span style=\"color: #000000\">.gpo.Computer.extensiondata.extension.ChildNodes<\/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\">Select-Object<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">name,<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">state<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #2b91af\">$regpolicyUserNodes1<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$xml1<\/span><span style=\"color: #000000\">.gpo.User.extensiondata.extension.ChildNodes<\/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\">Select-Object<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">name,<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">state<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #2b91af\">$regpolicyUserNodes2<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$xml2<\/span><span style=\"color: #000000\">.gpo.User.extensiondata.extension.ChildNodes<\/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\">Select-Object<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">name,<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">state<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>It is quite possible; in fact, it is a probability that one or more of the GPOs will not contain both the computer section and the user section of the GPO. An error will occur if you try to compare an empty GPO. Therefore, the <strong>if<\/strong> statement is used to determine if there is anything in the computer section or the user section of the GPO. If the variable is not null, a Try\/Catch block is used to perform the comparison using the <strong>Compare-Object<\/strong> cmdlet. When using the compare-object cmdlet, it is important to specify the property that will form the basis of the comparison. Otherwise, Windows PowerShell will pick a property that may or may not work well for your particular application. <\/p>\n<p>I am interested in GPOs that contain similar settings, and therefore I told the <strong>Compare-Object<\/strong> cmdlet to include equal settings that exist in the reference object and the difference object. If you are only looking for duplicate settings that exist in GPOs, you may wish to use the <strong>&ndash;excludedifferent<\/strong> switch so that your report will only contain duplicate settings. The order in which the GPOs are listed could make a difference depending on what you are looking for. It definitely will impact how you read the report that is generated. This section of the script is shown here:<\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #0000ff\">if<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #2b91af\">$computer<\/span><span style=\"color: #000000\">)<\/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\">Try<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\"> <\/p>\n<p>&#8220;Comparing Computer GPO&#8217;s $($gpoReports[0]) to $($gpoReports[1])`r`n&#8221; <\/p>\n<p><\/span><span style=\"color: #0000ff\">Compare-Object<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-ReferenceObject<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$regpolicyComputerNodes1<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">`<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">-DifferenceObject<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$regpolicyComputerNodes2<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-IncludeEqual<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">`<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">-property<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">name}<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>On the other hand, if one of the portions of the GPO is empty, the settings of the GPO that is not empty are listed on the Windows PowerShell console. This is shown here:<\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #000000\">Catch<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">[system.exception]<\/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: #0000ff\">if<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #2b91af\">$regPolicyComputerNodes1<\/span><span style=\"color: #000000\">)<\/span><span style=\"color: #808080\">&nbsp; <\/p>\n<p><\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\"> <\/p>\n<p>&#8220;Computer GPO $($gpoReports[0]) settings `r`f&#8221; <\/p>\n<p><\/span><span style=\"color: #2b91af\">$regPolicyComputerNodes1<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">}<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>If there are no settings to display from a particular GPO, a message to that effect is displayed on the Windows PowerShell console. This section of the script is shown here:<\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #0000ff\">else<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\"> &#8220;Computer GPO $($gpoReports[0]) not set&#8221; <\/span><span style=\"color: #000000\">}<\/span> <\/div>\n<p>The same code is repeated for the other computer node: <\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #0000ff\">if<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #2b91af\">$regPolicyComputerNodes2<\/span><span style=\"color: #000000\">)<\/span><span style=\"color: #808080\">&nbsp; <\/p>\n<p><\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\"> <\/p>\n<p>&#8220;Computer GPO $($gpoReports[1]) settings `r`f&#8221; <\/p>\n<p><\/span><span style=\"color: #2b91af\">$regPolicyComputerNodes2<\/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: #0000ff\">else<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\"> &#8220;Computer GPO $($gpoReports[1]) not set&#8221;<\/span><span style=\"color: #000000\">}<\/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\">catch<\/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\">computer<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>If a user section of the GPO exists, a Try\/Catch is used to attempt to compare the two user portions of the GPO. If an error occurs, the Catch block is used to determine which portion of the GPO is empty, and it will display a message indicating that the GPO is empty. If a GPO has settings, the settings will be displayed. This code, shown here, is nearly the same as that for the computer portion of the script:<\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #0000ff\">if<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #2b91af\">$user<\/span><span style=\"color: #000000\">)<\/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\">Try<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\"> <\/p>\n<p>&#8220;Comparing User GPO&#8217;s $($gpoReports[0]) to $($gpoReports[1])`r`n&#8221; <\/p>\n<p><\/span><span style=\"color: #0000ff\">Compare-Object<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-ReferenceObject<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$regpolicyUserNodes1<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">`<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">-DifferenceObject<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$regpolicyUserNodes2<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-SyncWindow<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #800000\">5<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-IncludeEqual<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">`<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">-property<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">name}<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">Catch<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">[system.exception]<\/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: #0000ff\">if<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #2b91af\">$regPolicyUserNodes1<\/span><span style=\"color: #000000\">)<\/span><span style=\"color: #808080\">&nbsp; <\/p>\n<p><\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\"> <\/p>\n<p>&#8220;User GPO $($gpoReports[0]) settings `r`f&#8221; <\/p>\n<p><\/span><span style=\"color: #2b91af\">$regPolicyUserNodes1<\/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: #0000ff\">else<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\"> &#8220;User GPO $($gpoReports[0]) not set&#8221; <\/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: #2b91af\">$regPolicyUserNodes2<\/span><span style=\"color: #000000\">)<\/span><span style=\"color: #808080\">&nbsp; <\/p>\n<p><\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\"> <\/p>\n<p>&#8220;User GPO $($gpoReports[1]) settings `r`f&#8221; <\/p>\n<p><\/span><span style=\"color: #2b91af\">$regPolicyUserNodes2<\/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: #0000ff\">else<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\"> &#8220;User GPO $($gpoReports[1]) not set&#8221;<\/span><span style=\"color: #000000\">}<\/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\">}<\/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\">catch<\/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\">compare-XMLGPO<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>When testing the script to ensure it reports accurately the settings in my two GPO files, I used the compare feature in XML Notepad. The compare feature is under <strong>View<\/strong>\/<strong>Compare XML Files<\/strong>. As shown in the following image, the color coding makes it easy to spot modifications, additions, and deletions. <\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1586.hsg071610021_2786EC54.jpg\"><img decoding=\"async\" style=\"border-bottom: 0px;border-left: 0px;border-top: 0px;border-right: 0px\" title=\"Image of color coding\" border=\"0\" alt=\"Image of color coding\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7245.hsg071610021_thumb_792D66A6.jpg\" width=\"604\" height=\"439\" \/><\/a> <\/p>\n<p>The entry point to the script first determines if the <strong>&ndash;user<\/strong> or<strong>&ndash;computer<\/strong> switch has been used. If neither is present, the script displays a message and exits. You could change this behavior and set one or the other as the default. The code to do this is shown here:<\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #0000ff\">if<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #0000ff\">-not<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #2b91af\">$user<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">-or<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$computer<\/span><span style=\"color: #000000\">))<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\"> &#8220;using default user GPO&#8221; <\/span><span style=\"color: #0000ff\">;<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$user<\/span><span style=\"color: #0000ff\">=<\/span><span style=\"color: #2b91af\">$true<\/span><span style=\"color: #000000\">}<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>The code as it exists in the Compare-GPO.ps1 script is shown here: <\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #0000ff\">if<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #0000ff\">-not<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #2b91af\">$user<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #0000ff\">-or<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$computer<\/span><span style=\"color: #000000\">))<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\"> &#8220;Please specify either -computer or -user when running script&#8221; <\/span><span style=\"color: #0000ff\">;<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">exit}<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>The <strong>Get-MyModule<\/strong> function is used to load the <strong>GroupPolicy<\/strong> module. If the module is not found on the system, the script exits:<\/p>\n<p>&nbsp;<\/p>\n<div class=\"code\"><span style=\"color: #0000ff\">If<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #0000ff\">-not<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">(Get-MyModule<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-name<\/span><span style=\"color: #808080\"> &#8220;GroupPolicy&#8221;<\/span><span style=\"color: #000000\">))<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">{<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">exit<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">}<\/span> <\/div>\n<p>Next, the <strong>Get-GpoAsXML<\/strong> function is used to retrieve the two GPOs specified in the <strong>$gponame<\/strong> variable. The <strong>Get-GpoAsXML<\/strong> function returns the path to the two GPOs. This returned array of paths is stored in the <strong>$gpoReports<\/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: #000000\">Get-GpoAsXML<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-gponame<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$gponame<\/span><span style=\"color: #000000\">.split(<\/span><span style=\"color: #808080\">&#8220;,&#8221;<\/span><span style=\"color: #000000\">)<\/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: #808080\">&nbsp;<\/span><span style=\"color: #000000\">`<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/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\">-folder<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$folder<\/span><span style=\"color: #808080\"> <\/p>\n<p><\/span><span style=\"color: #000000\">The<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">last<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">thing<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">the<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">script<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">does<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">is<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">call<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">the<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">Compare-XMLGPO<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">function,<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">as<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">shown<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">here:<\/span><span style=\"color: #808080\">&nbsp; <\/p>\n<p><\/span><span style=\"color: #000000\">Compare-XMLGPO<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-gpoReports<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$gpoReports<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-user<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$user<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #000000\">-computer<\/span><span style=\"color: #808080\">&nbsp;<\/span><span style=\"color: #2b91af\">$computer<\/span> <\/div>\n<p>&nbsp;<\/p>\n<p>When the script runs, output is shown similar to that in the following image. When testing a script that uses switched parameters in the Windows PowerShell ISE, I will set the switched value to <strong>$true<\/strong>. This is also seen in the following image.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5618.hsg071610031_78C133B1.jpg\"><img decoding=\"async\" style=\"border-bottom: 0px;border-left: 0px;border-top: 0px;border-right: 0px\" title=\"Image of script output\" border=\"0\" alt=\"Image of script output\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4628.hsg071610031_thumb_5839F3FF.jpg\" width=\"604\" height=\"454\" \/><\/a> <\/p>\n<p>SV, that is all there is to using Windows PowerShell to compare two XML Group Policy objects. This also concludes Group Policy Week. Join us tomorrow for <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/tags\/weekend+scripter\/\">Weekend Scripter<\/a> when we will talk about using Windows PowerShell to clean up a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Comma-separated_values\">CSV<\/a> file. <\/p>\n<p>We would love for you to <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,4,45,165],"class_list":["post-17741","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-group-policy","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell","tag-xml"],"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\/17741","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=17741"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/17741\/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=17741"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=17741"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=17741"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}