{"id":54403,"date":"2009-02-12T21:10:00","date_gmt":"2009-02-12T21:10:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/02\/12\/hey-scripting-guy-how-can-i-generate-a-list-of-my-group-policy-objects\/"},"modified":"2009-02-12T21:10:00","modified_gmt":"2009-02-12T21:10:00","slug":"hey-scripting-guy-how-can-i-generate-a-list-of-my-group-policy-objects","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-generate-a-list-of-my-group-policy-objects\/","title":{"rendered":"Hey, Scripting Guy! How Can I Generate a List of My Group Policy Objects?"},"content":{"rendered":"<h2><img decoding=\"async\" class=\"nearGraphic\" 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\"> <\/h2>\n<p>Hey, Scripting Guy! We have a number of Group Policy Objects (GPOs) that are not really doing anything. In fact, they are about as useless as an old hound dog with sinus problems. What I need is an easy way to find these old GPOs and produce a list so I can decide if I wish to delete them. Can you help me?<\/p>\n<p>&#8211; JG<\/p>\n<p><img decoding=\"async\" border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><img decoding=\"async\" class=\"nearGraphic\" 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>Hi JG,<\/p>\n<p>&#8220;That dog won&#8217;t hunt.&#8221; I am not sure exactly what that means, but it is the only dog expression I know. I guess because I am living in the Southern part of the United States, I should study Southern speakr more closely. After all they have words down here that are not used in the rest of the United States. Words like <i>haintnarynone<\/i>, which is a reply to the question, &#8220;Do you have any more milk?&#8221; When you pronounce <i>haintnarynone<\/i> , you say it in one syllable without moving your lips. You can learn this technique by grasping your upper and lower lip between the thumb and the forefinger, and then saying \u201chaintnarynone.\u201d However, I digress. (Let it never be said that a Scripting Guy became distracted during the process of writing a \u201cHey, Scripting Guy!\u201d article. Well, okay, maybe once in a while: A quick search of the Script Center for the word \u201cdistracted\u201d returns eight hits. So 9 times we became distracted. We\u2019ll take that average.) <\/p>\n<p>Where were we? Oh, yeah. I talked to my neighbor, and he said the kind of dog you want depends on what you are hunting. Oh wait, the dog won&#8217;t hunt. Sorry. I don\u2019t really know much about dogs at all, so let&#8217;s talk about Group Policy scripting instead.<\/p>\n<p>        var sortedCol = new Array();        var sortFactor = new Array();        var initialSort = new Array();        function rowData(index, value)        {        this.index = index;        this.value = value;        }        var compareFactor;        function compareValues(a, b)        {        if (a.value <b> b.value)        return compareFactor;        return 0;        }        function sortByColumn(tableIndex, tdName, order)        {                  var td = document.getElementById(tdName);          var cols = td.parentElement.children;          var col = -1;          for (var i=0; i &lt; cols.length; i++)          if (cols[i] == td)          col = i;          if (col == -1)          return;          if (td != sortedCol[tableIndex] &amp;&amp; sortedCol[tableIndex] != null)          {          sortedCol[tableIndex].className = &quot;sortable&quot;;          sortedCol[tableIndex].getElementsByTagName(&quot;IMG&quot;)[0].src=&quot;http:\/\/blogs.technet.com\/library\/gallery\/templates\/MNP2.GenericArticle\/..\/MNP2.Common\/images\/sortNone.gif&quot;;          }          if (td == sortedCol[tableIndex])          {          sortFactor[tableIndex] = -sortFactor[tableIndex];          }          else          {          sortedCol[tableIndex] = td;          if (!initialSort) sortFactor[tableIndex] = 1;          td.className = &quot;selectedSort&quot;;          }          if (sortFactor[tableIndex] == 1)          td.getElementsByTagName(&quot;IMG&quot;)[0].src=&quot;http:\/\/blogs.technet.com\/library\/gallery\/templates\/MNP2.GenericArticle\/..\/MNP2.Common\/images\/sortAscending.gif&quot;;          else          td.getElementsByTagName(&quot;IMG&quot;)[0].src=&quot;http:\/\/blogs.technet.com\/library\/gallery\/templates\/MNP2.GenericArticle\/..\/MNP2.Common\/images\/sortDescending.gif&quot;;          initialSort = false;          var thead = td.parentElement.parentElement;          var tbody = thead.nextSibling;          var table = thead.parentElement;          var rows = tbody.getElementsByTagName(&quot;TR&quot;);          var data = new Array();          var hasEvenRowShading = false;          for (var i=0; i &lt; rows.length; i++)          if (rows[i].parentElement == tbody)          {          if (rows[i].className == &quot;evenRecord&quot;)          hasEvenRowShading = true;          var cell = rows[i].children[col];          var value = cell.getAttribute(&quot;value&quot;);          if (value == null)          value = cell.innerText;          if (order == &#039;numerical&#039;)          {          var filterChars = new Array(&quot;$&quot;, &quot;\u00a2&quot;, &quot;\u00a3&quot;, &quot;\u00a4&quot;, &quot;\u00a5&quot;, &quot;&#8355;&quot;, &quot;&#8356;&quot;, &quot;&#8359;&quot;, &quot;&#8362;&quot;, &quot;&#8363;&quot;, &quot;&#8364;&quot;, &quot;,&quot;, &quot;.&quot;);          for (var j=0; j &lt; filterChars.length; j++)          value = value.replace(filterChars[j], &quot;&quot;);          value = parseFloat(value);          if (isNaN(value))          value = Number.NEGATIVE_INFINITY;          }          if (order == &#039;chronological&#039;)          value = Date.parse(value);          data[i] = new rowData(i, value);          }          compareFactor = sortFactor[tableIndex];          data = data.sort(compareValues);          var tbody2 = document.createElement(&quot;TBODY&quot;);          for (var i=0; i &lt; data.length; i++)          if (data[i])          {          var row = rows[data[i].index].cloneNode(true);          if ((i % 2 == 0) || !hasEvenRowShading)          row.className = &quot;record&quot;;          else          row.className = &quot;evenRecord&quot;;          tbody2.appendChild(row);          }          table.replaceChild(tbody2, tbody);                }      <\/p>\n<table id=\"E6C\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">This week is Group Policy week. We will spend the week looking at some of the things you can do using Windows PowerShell when you have access to the COM object that ships with the Group Policy Management Console. There are some good VBScripts that illustrate working with Group Policy in the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/default.mspx?mfr=true\">Script Center Script Repository<\/a>, and in the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/csc\/scripts\/policy\/default.mspx\">Community-Submitted Scripts Center<\/a>. You can also download a collection of <a href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?FamilyID=38c1a89b-a6d2-4f2a-a944-9236999aee65&amp;DisplayLang=en\">sample Group Policy management scripts<\/a>.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>To find Group Policy objects that do not have any security filtering associated with them, you can use the <b>FindGPOsWithNoSecurityFiltering.ps1<\/b> script which is seen here. To obtain help on the script you can use the following syntax:<\/p>\n<pre class=\"codeSample\">FindGPOsWithNoSecurityFiltering.ps1 \u2013help<\/pre>\n<p><b>FindGPOsWithNoSecurityFiltering.ps1<\/b><\/p>\n<pre class=\"codeSample\"><pre class=\"codeSample\">param(\n      $domain=$env:userDNSdomain,\n      [switch]$query,\n      [switch]$help,\n      [switch]$examples,\n      [switch]$min,\n      [switch]$full\n      ) #end param\n# Begin Functions\nfunction Get-HelpTopic()\n{\n $descriptionText= `\n@\"\n NAME: FindGPOsWithNoSecurityFiltering.ps1\n DESCRIPTION:\n Finds GPOs that have no security filtering\n assigned, and therefore they apply to no one\n PARAMETERS:\n -domain domain to query for orphaned gpos\n -query causes query to execute\n -help prints help description and parameters file\n -examples prints only help examples of syntax\n -full prints complete help information\n -min prints minimal help. Modifies -help\n\"@ #end descriptionText\n$examplesText= `\n@\"\n SYNTAX:\n FindGPOsWithNoSecurityFiltering.ps1\n Displays an error missing query, and calls help\n FindGPOsWithNoSecurityFiltering.ps1  -query\n Queries current domain for GPOs with no security\n filter applied to them\n FindGPOsWithNoSecurityFiltering.ps1 -domain nwtraders.com -query\n Queries nwtraders.com domain for GPOs with no security\n filter applied to them\n FindGPOsWithNoSecurityFiltering.ps1 -help\n Prints the help topic for the script\n FindGPOsWithNoSecurityFiltering.ps1 -help -full\n Prints full help topic for the script\n FindGPOsWithNoSecurityFiltering.ps1 -help -examples\n Prints only the examples for the script\n FindGPOsWithNoSecurityFiltering.ps1 -examples\n Prints only the examples for the script\n\"@ #end examplesText\n$remarks = `\n\"\nREMARKS\n     For more information, type: $($MyInvocation.ScriptName) -help -full\n\" #end remarks\n  if($examples) { $examplesText ; $remarks ; exit }\n  if($full)     { $descriptionText; $examplesText ; exit }\n  if($min)      { $descriptionText ; exit }\n  $descriptionText; $remarks\n  exit\n} #end Get-HelpTopic function\nfunction New-Line (\n                  $strIN,\n                  $char = \"=\",\n                  $sColor = \"Yellow\",\n                  $uColor = \"darkYellow\",\n                  [switch]$help\n                 )\n{\n if($help)\n  {\n    $local:helpText = `\n@\"\n     New-Line accepts inputs: -strIN for input string and -char for seperator\n     -sColor for the string color, and -uColor for the underline color. Only\n     the -strIn is required. The others have the following default values:\n     -char: =, -sColor: Yellow, -uColor: darkYellow\n     Example:\n     New-Line -strIN \"Hello world\"\n     New-Line -strIn \"Morgen welt\" -char \"-\" -sColor \"blue\" -uColor \"yellow\"\n     New-Line -help\n\"@\n   $local:helpText\n   break\n  } #end New-Line help\n $strLine= $char * $strIn.length\n Write-Host -ForegroundColor $sColor $strIN\n Write-Host -ForegroundColor $uColor $strLine\n} #end New-Line function\nFunction Get-NoFilter()\n{\n $gpm = new-object -comobject gpmGMT.gpm\n $constants = $gpm.getConstants()\n $gpmDomain = $gpm.GetDomain($domain,$null,$constants.useanydc)\n $gpmSearchCriteria = $gpm.CreateSearchCriteria()\n $gpoList = $gpmDomain.SearchGpos($gpmSearchCriteria)\n $perm = $Constants.PermGPOApply\n foreach($gpo in $gpoList)\n  {\n   $secInfo = $gpo.GetSecurityInfo()\n    foreach($secPerm in $secInfo)\n     {\n      if($secPerm.Permission -ne $perm)\n         {\n           $errorActionPreference = \"SilentlyContinue\"\n           $hash += @{ $gpo.id = $gpo.DisplayName }\n           $errorActionPreference = \"continue\"\n         } #end if\n     } #end foreach\n  } #end foreach\n  New-Line(\"No permissions were found $($hash.count) GPOs\")\n  format-table -inputobject $hash -autosize\n exit\n} #end Get-NoFilter\n# Entry Point\nif($help)      { Get-HelpTopic }\nif($examples)  { Get-HelpTopic }\nif($full)      { Get-HelpTopic }\nif($query)    { Get-NoFilter }\nif(!$query) { \"missing query .. \" ; Get-HelpTopic }\n<\/pre>\n<p>&nbsp;<\/p>\n<p>The <b>FindGPOsWithNoSecurityFiltering.ps1<\/b> script is written in the same style as the other GPO scripts we have seen this week. Please refer to the articles from <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/feb09\/hey0209.mspx\" target=\"_blank\">Monday<\/a> and <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/feb09\/hey0210.mspx\" target=\"_blank\">Tuesday<\/a> to see information about the command-line parameters, the help function, and the <b>New-Line<\/b> function.<\/p>\n<p>The core script functionality is the <b>Get-NoFilter<\/b> function, which is used to find GPOs that have no security filter applied. The first thing we do in the function is to create an instance of the <b>gpmGMT.gpm<\/b> object. Because the object is a COM object we use the <b>\u2013comobject<\/b> parameter of the <b>New-Object <\/b>cmdlet. We store the returned object in the <b>$gpm<\/b> variable as seen here:<\/p>\n<pre class=\"codeSample\">$gpm = new-object -comobject gpmGMT.gpm<\/pre>\n<p>After we have created the <b>gpmGMT.gpm<\/b> object, we have access to the methods seen in Table 1.<\/p>\n<p>        var tableId = &#8220;EFF&#8221;;        sortedCol[tableId] = null;        sortFactor[tableId] = 1;        initialSort[tableId] = true;      <\/p>\n<table id=\"EFF\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead>\n<tr>\n<td class=\"tableHeader\" colSpan=\"3\">Table 1 Methods of the GpmGMT.gpm object<\/td>\n<\/tr>\n<tr class=\"sortable\" vAlign=\"top\">\n<td id=\"colEJF\" class=\"sortable\"><a href=\"sortByColumn('EFF', 'colEJF', '')\"><\/p>\n<table cellSpacing=\"0\" cellPadding=\"0\" width=\"100%\">\n<tbody>\n<tr>\n<td width=\"100%\">Name<\/td>\n<td align=\"right\"><img decoding=\"async\" title=\"\" alt=\"*\" src=\"http:\/\/www.microsoft.com\/library\/gallery\/templates\/MNP2.Common\/images\/sortNone.gif\" width=\"8\" height=\"8\"><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/a><\/td>\n<td id=\"colENF\" class=\"sortable\"><a href=\"sortByColumn('EFF', 'colENF', '')\"><\/p>\n<table cellSpacing=\"0\" cellPadding=\"0\" width=\"100%\">\n<tbody>\n<tr>\n<td width=\"100%\">MemberType<\/td>\n<td align=\"right\"><img decoding=\"async\" title=\"\" alt=\"*\" src=\"http:\/\/www.microsoft.com\/library\/gallery\/templates\/MNP2.Common\/images\/sortNone.gif\" width=\"8\" height=\"8\"><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/a><\/td>\n<td id=\"colERF\" class=\"sortable\"><a href=\"sortByColumn('EFF', 'colERF', '')\"><\/p>\n<table cellSpacing=\"0\" cellPadding=\"0\" width=\"100%\">\n<tbody>\n<tr>\n<td width=\"100%\">Definition<\/td>\n<td align=\"right\"><img decoding=\"async\" title=\"\" alt=\"*\" src=\"http:\/\/www.microsoft.com\/library\/gallery\/templates\/MNP2.Common\/images\/sortNone.gif\" width=\"8\" height=\"8\"><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/a><\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">CreateMigrationTable<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IGPMMigrationTable CreateMigrationTable ()<\/p>\n<\/td>\n<\/tr>\n<tr class=\"evenRecord\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">CreatePermission<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IGPMPermission CreatePermission (string, GPMPermissionType, bool)<\/p>\n<\/td>\n<\/tr>\n<tr class=\"record\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">CreateSearchCriteria<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IGPMSearchCriteria CreateSearchCriteria ()<\/p>\n<\/td>\n<\/tr>\n<tr class=\"evenRecord\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">CreateTrustee<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IGPMTrustee CreateTrustee (string)<\/p>\n<\/td>\n<\/tr>\n<tr class=\"record\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">GetBackupDir<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IGPMBackupDir GetBackupDir (string)<\/p>\n<\/td>\n<\/tr>\n<tr class=\"evenRecord\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">GetBackupDirEx<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IGPMBackupDirEx GetBackupDirEx (string, GPMBackupType)<\/p>\n<\/td>\n<\/tr>\n<tr class=\"record\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">GetClientSideExtensions<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IGPMCSECollection GetClientSideExtensions ()<\/p>\n<\/td>\n<\/tr>\n<tr class=\"evenRecord\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">GetConstants<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IGPMConstants GetConstants ()<\/p>\n<\/td>\n<\/tr>\n<tr class=\"record\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">GetDomain<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IGPMDomain GetDomain (string, string, int)<\/p>\n<\/td>\n<\/tr>\n<tr class=\"evenRecord\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">GetMigrationTable<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IGPMMigrationTable GetMigrationTable (string)<\/p>\n<\/td>\n<\/tr>\n<tr class=\"record\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">GetRSOP<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IGPMRSOP GetRSOP (GPMRSOPMode, string, int)<\/p>\n<\/td>\n<\/tr>\n<tr class=\"evenRecord\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">GetSitesContainer<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">IGPMSitesContainer GetSitesContainer (string, string, string, int)<\/p>\n<\/td>\n<\/tr>\n<tr class=\"record\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">InitializeReporting<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">void InitializeReporting (string)<\/p>\n<\/td>\n<\/tr>\n<tr class=\"evenRecord\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">InitializeReporting<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">Method<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">void InitializeReportingEx (string, int)<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>The next thing we need to do is to create the constants and to store them in a variable. We talked about Group Policy constants in <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/feb09\/hey0211.mspx\" target=\"_blank\">Wednesday\u2019s \u201cHey, Scripting Guy!\u201d article<\/a>, and the process and purpose is exactly the same as what we do here:<\/p>\n<pre class=\"codeSample\">$constants = $gpm.getConstants()<\/pre>\n<p>Now we need to connect to the domain. To do that, we use the <b>GetDomain<\/b> method and pass it the name of the domain and the <b>useanydc<\/b> constant. We store the returned object in the <b>$gpmDomain<\/b> variable. Next we need to create the search criteria. To do this, we use the <b>CreateSearchCriteria<\/b> method and store the returned search criteria in the <b>$gpmSearchCriteria<\/b> variable. We then use the <b>SearchGpos<\/b> method from the domain we stored in the $<b>gpmDomain<\/b> variable. We give the <b>SearchGpos<\/b> method the search criteria we created in the previous line. This is seen here:<\/p>\n<pre class=\"codeSample\">$gpmDomain = $gpm.GetDomain($domain,$null,$constants.useanydc)\n$gpmSearchCriteria = $gpm.CreateSearchCriteria()\n$gpoList = $gpmDomain.SearchGpos($gpmSearchCriteria)\n<\/pre>\n<p>We now need to retrieve a specific constant from all the constants we have stored in the <b>$constants<\/b> variable. The specific one we need is called <b>PermGPOApply<\/b>, and it is used to specify that the GPO has permissions applied. This is seen here, where we store the resultant constant in the <b>$perm<\/b> variable:<\/p>\n<pre class=\"codeSample\">$perm = $Constants.PermGPOApply\n<\/pre>\n<p>We are now ready to begin examining each of the GPOs. We first use the <b>ForEach<\/b> statement to work through each of the GPOs that is stored in the <b>$gpoList<\/b> variable. We take each one of the GPOs and call the <b>GetSecurityInfo<\/b> method to retrieve the security information that is associated with each of the GPOs. We store the security information in the <b>$secInfo <\/b>variable: <\/p>\n<pre class=\"codeSample\">foreach($gpo in $gpoList)\n  {\n   $secInfo = $gpo.GetSecurityInfo()\n<\/pre>\n<p>When we have the security information, we need to examine each permission that makes up the security information attached to the GPO. If the permission is not equal to the <b>PermGPOApply<\/b> constant, we add the name of the GPO to the hash table we create with the name of <b>$hash<\/b>. A hash table is similar to the VBScript concept of a <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/begin\/ss0906.mspx\" target=\"_blank\">dictionary object<\/a>. Before and after each attempt to obtain the display name, we use <b>$errorActionPreference = &#8220;SilentlyContinue&#8221;<\/b>, which is the same as VBScript <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/guide\/sas_vbs_efuo.mspx?mfr=true\" target=\"_blank\">On Error Resume Next<\/a>. By setting <b>$errorActionPreference<\/b> equal to &#8220;continue&#8221;, in this case it is similar to using <b>On Error Goto 0<\/b>, which is <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/scriptshop\/shop1205.mspx\" target=\"_blank\">discussed here<\/a>.<\/p>\n<pre class=\"codeSample\">foreach($secPerm in $secInfo)\n     {\n      if($secPerm.Permission -ne $perm)\n         {\n           $errorActionPreference = \"SilentlyContinue\"\n           $hash += @{ $gpo.id = $gpo.DisplayName }\n           $errorActionPreference = \"continue\"\n         } #end if\n     } #end foreach\n  } #end foreach\n<\/pre>\n<p>It is time to produce our report. We use the <b>count<\/b> property from the <b>hashtable<\/b> object to tell us how many GPOs were found without permissions. We then call the <b>Format-Table<\/b> cmdlet to print out the hash table:<\/p>\n<pre class=\"codeSample\">New-Line(\"No permissions were found $($hash.count) GPOs\")\n  format-table -inputobject $hash \u2013autosize\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Well, JG, I believe that &#8220;this dog <i>will<\/i> hunt!&#8221; This concludes our Group Policy scripts. The next time we write about Group Policy, Windows 2008 R2 will be out and the scripts will be much cleaner as we will also take advantage of the help features of Windows PowerShell 2.0. If you can&#8217;t wait, go ahead and download Windows 2008 R2 and start playing around with it. I am running it on one of my laptops with Hyper-V and it rocks! Join us tomorrow for Quick-Hits Friday where we will tackle a <a href=\"http:\/\/encarta.msn.com\/dictionary_1861691082\/grab_bag.html\" target=\"_blank\">grab bag<\/a> of questions. Until then, peace.<\/p>\n<p>&nbsp;<\/p>\n<p><b>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/b><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! We have a number of Group Policy Objects (GPOs) that are not really doing anything. In fact, they are about as useless as an old hound dog with sinus problems. What I need is an easy way to find these old GPOs and produce a list so I can decide if I [&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-54403","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>Hey, Scripting Guy! We have a number of Group Policy Objects (GPOs) that are not really doing anything. In fact, they are about as useless as an old hound dog with sinus problems. What I need is an easy way to find these old GPOs and produce a list so I can decide if I [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54403","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=54403"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54403\/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=54403"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=54403"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=54403"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}