{"id":54433,"date":"2009-02-09T21:05:00","date_gmt":"2009-02-09T21:05:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/02\/09\/hey-scripting-guy-how-can-i-list-all-group-policy-objects-in-a-domain\/"},"modified":"2009-02-09T21:05:00","modified_gmt":"2009-02-09T21:05:00","slug":"hey-scripting-guy-how-can-i-list-all-group-policy-objects-in-a-domain","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-list-all-group-policy-objects-in-a-domain\/","title":{"rendered":"Hey, Scripting Guy! How Can I List All Group Policy Objects in a Domain?"},"content":{"rendered":"<h2><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> <\/h2>\n<p>Hey, Scripting Guy! Do you ever wonder how some people ever get their jobs? We had a guy who was hired to organize our Group Policy implementation. The person was a loser. I mean, I do not think he could even spell Group Policy. Needless to say, the whole thing has morphed into some kind of <a href=\"http:\/\/www.earth-photography.com\/Countries\/England\/England_London_StatueElephant.html\">Salvador Dali Space Elephant<\/a> that bears little resemblance to the original plan. I know you wrote a book on Active Directory design a few years ago, and I would love to hire you to come straighten this mess out, but I guess that is out of the question. Can I at least get you to write me a script that will tell me what Group Policy objects we have?<\/p>\n<p>&#8211; LW<\/p>\n<p><img decoding=\"async\" height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"><\/p>\n<p>Hi LW,<\/p>\n<p>So you are the one that bought a copy of that book. Thanks. I wrote a series of Windows PowerShell scripts for the <a href=\"http:\/\/www.microsoft.com\/learning\/en\/us\/Books\/10345.aspx\">Windows Server 2008 Resource Kit<\/a>; 10 of the scripts were for Group Policy. In Windows Server 2008 R2, there is a series of Group Policy cmdlets that provide for native Windows PowerShell support. We can also use the COM object that ships with the Group Policy Management Console. The cool thing about this is that the Group Policy Management Console is included in the <a href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?FamilyID=9ff6e897-23ce-4a36-b7fc-d52065de9960&amp;DisplayLang=en\">Microsoft Remote Server Administration Tools (RSAT Tools) for Windows Vista<\/a>. You can also download it for <a href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?FamilyId=0A6D4C24-8CBD-4B35-9272-DD3CBFC81887&amp;displaylang=en\">other versions of the Windows operating system<\/a>. On Windows Server 2008, you gain access to the Group Policy Management Console when you install the Group Policy Management feature from within Server Manager. <\/p>\n<table class=\"dataTable\" id=\"EID\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\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>The <b>ListAllGPOs.ps1<\/b> script will list all Group Policy Objects (GPOs) in your current domain. You can query for a list of all GPOs in your current domain by running the script with the <b>-q<\/b> switch. If you use <b>-q<\/b> and <b>-v<\/b>, you will get a GPO verbose listing, which includes detailed information about the Group Policy objects. Help with the syntax can be obtained by using <b>-h<\/b>, <b>-e<\/b>, and <b>-f<\/b>. You can type the full switch names if you wish, but there is no real reason to do so unless you just feel the need to practice your typing skills. Here are a few examples of the syntax for launching thescript: <\/p>\n<pre class=\"codeSample\">ListAllGPOs.ps1 -q\nListAllGPOs.ps1 -q -v\nListAllGPOs.ps1 -h\nListAllGPOs.ps1 -e\nListAllGPOs.ps1 -f\n<\/pre>\n<p>The complete <b>ListALlGPOs.ps1<\/b> script is seen here:<\/p>\n<p><b>ListAllGPOs.ps1<\/b><\/p>\n<pre class=\"codeSample\"><pre class=\"codeSample\">param(\n      $domain = $env:userDNSdomain,\n      [switch]$query,\n      [switch]$verbose,\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: ListAllGPOs.ps1\n DESCRIPTION:\n Returns detailed information about all GPOs in\n the selected domain\n PARAMETERS:\n -domain domain to return GPO information\n -query perform the query. By default returns name\n  and guid of GPO\n -verbose returns extended GPO information\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 ListAllGPOs.ps1\n Displays an error missing query, and calls help\n ListAllGPOs.ps1  -query\n Lists name and guid of the GPOs in current domain\n ListAllGPOs.ps1 -query -domain \"nwtraders.com\" -verbose\n Lists detailed GPO information about the GPOs in\n nwtraders.com domain\n ListAllGPOs.ps1 -help\n Prints the help topic for the script\n ListAllGPOs.ps1 -help -full\n Prints full help topic for the script\n ListAllGPOs.ps1 -help -examples\n Prints only the examples for the script\n ListAllGPOs.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-GPO()\n{\n New-Line(\"Listing GPOs from $domain\")\n $gpm=New-Object -ComObject gpmgmt.gpm\n $constants = $gpm.GetConstants()\n $gpmDomain = $gpm.GetDomain($domain,$null,$constants.useanydc)\n $gpmSearchCriteria = $gpm.CreateSearchCriteria()\n $gpo=$gpmdomain.SearchGPOs($gpmSearchCriteria)\n if($verbose)\n  {\n   $gpo\n  }\n ELSE\n  {\n   foreach($ogpo in $gpo)\n    {\n     $hash += @{ $ogpo.ID = $ogpo.DisplayName }\n    }\n     format-table -inputobject $hash -autosize\n  } #end else\n exit\n} #end Get-GPO\n# Entry Point\nif($help)      { Get-HelpTopic }\nif($examples)  { Get-HelpTopic }\nif($full)      { Get-HelpTopic }\nif($query)     { Get-GPO }\nif(!$query)    { \"Missing query\" ; Get-HelpTopic }\n<\/pre>\n<p>The first thing we do in the <b>ListAllGPOs.ps1<\/b> script is define some command-line parameters. The command-line parameters are used to control the way the script behaves at run time. They are very similar to the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/guide\/sas_wsh_ywsa.mspx?mfr=true\">VBScript command-line arguments<\/a>. If you want to supply a default value for a command-line parameter, you make a value assignment when you specify the variable that will be used to hold the parameter. If you want to make a switched parameter, you use the <b>[switch]<\/b> type alias to convert the parameter from a normal parameter to a switched parameter. A switched parameter is one that is a Boolean value (yes\/no, true\/false), and it only does something when it is present. If the switched parameter is not present on the command line, it is ignored. You do not supply a value when you use a switched parameter, because its very presence changes the behavior of the script: <\/p>\n<pre class=\"codeSample\">param(\n      $domain = $env:userDNSdomain,\n      [switch]$query,\n      [switch]$verbose,\n      [switch]$help,\n      [switch]$examples,\n      [switch]$min,\n      [switch]$full\n      ) #end param\n<\/pre>\n<p>The first function we come to in the script is the <b>Get-HelpTopic<\/b> function. The <b>Get-HelpTopic<\/b> function consumes most of the lines in the script. It is made up of a series of <b>Here-Strings<\/b>. <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/pstips\/jun07\/pstip0629.mspx\">Here-Strings<\/a> allow you to type information without worrying about things such as escaping special characters. It is a what-you-see-is-what-you-get (<a href=\"http:\/\/en.wikipedia.org\/wiki\/Wysiwyg\">WYSIWYG<\/a>) sort of thing that makes it perfect for developing command-line Help for your script. The <b>Get-HelpTopic<\/b> function is essentially three large <b>Here-Strings<\/b>, each of which is assigned to a separate variable. The contents of a particular variable are displayed based upon which switched parameter is supplied from the command line. For more information about this technique, you can refer to the Microsoft Press book, <a href=\"http:\/\/www.microsoft.com\/MSPress\/books\/authors\/auth9541.aspx\">Windows PowerShell Scripting Guide<\/a>. The <b>Get-HelpTopic<\/b> function is seen here, with most of the <b>Here-Strings<\/b> edited out (this will allow you to study the way the function works, without the distraction of dozens of lines of text; the complete function is, of course, shown in the program listing at the beginning of this article):<\/p>\n<pre class=\"codeSample\">function Get-HelpTopic()\n{\n $descriptionText= `\n@\"\n NAME: ListAllGPOs.ps1\n DESCRIPTION:\n\"@\n$examplesText= `\n@\"\n SYNTAX:\n ListAllGPOs.ps1\n\"@\n$remarks = `\n\"\nREMARKS\n\"@\nif($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\n<\/pre>\n<p>The <b>New-Line<\/b> function is based upon a function I wrote years ago in VBScript. I have since modified it nearly a dozen times, but the essential capabilities remain the same. It takes the length of a line of text, and creates a line of text that is exactly the same length as the data that is being highlighted via the underline. It is a wonderful function (if I do say so myself), and I used it so much, it is included in my Windows PowerShell profile. The working code for the function (without the associated Help text) is seen&nbsp;here: <\/p>\n<pre class=\"codeSample\">$strLine= $char * $strIn.length\n Write-Host -ForegroundColor $sColor $strIN\n Write-Host -ForegroundColor $uColor $strLine\n<\/pre>\n<p>The essential functionality of the script is contained in the <b>Get-GPO<\/b> function. To work with Group Policy, we need to create an instance of the <b>gpmgmt.gpm<\/b> COM object. To do this, we use the <b>New-Object<\/b> cmdlet with the <b>-ComObject<\/b> parameter as seen here: <\/p>\n<pre class=\"codeSample\">$gpm=New-Object -ComObject gpmgmt.gpm<\/pre>\n<p>Next we need to retrieve the constants we will use when we connect to the domain. To obtain the constants, all we need to do is use the <b>GetConstants<\/b> method as seen here:<\/p>\n<pre class=\"codeSample\">$constants = $gpm.GetConstants()<\/pre>\n<p>Now we need to connect to the domain. To do this, we use the <b>GetDomain<\/b> method and pass it the domain name, which we have stored in the <b>$domain<\/b> variable, and we use the constant, which allows us to connect to any domain controller:<\/p>\n<pre class=\"codeSample\">$gpmDomain = $gpm.GetDomain($domain,$null,$constants.useanydc)<\/pre>\n<p>Now we need to create the search criteria. To do this, we use the <b>CreateSearchCriteria<\/b> method. The returned <b>SearchCriteria<\/b> object is stored in the <b>$gpmSearchCriteria<\/b> variable and passed to the <b>SearchGPO<\/b> method as seen here:<\/p>\n<pre class=\"codeSample\">$gpmSearchCriteria = $gpm.CreateSearchCriteria()\n$gpo=$gpmdomain.SearchGPOs($gpmSearchCriteria)\n<\/pre>\n<p>When we have the collection of Group Policy objects, we now look to see if the script was run with the <b>-verbose<\/b> parameter. If it was, we display all the information about the Group Policy object. If the script was not run with the <b>-verbose<\/b> parameter, we display only the name of the GPO. The code that makes this determination is seen&nbsp;here:<\/p>\n<pre class=\"codeSample\">if($verbose)\n  {\n   $gpo\n  }\n ELSE\n  {\n   foreach($ogpo in $gpo)\n    {\n     $hash += @{ $ogpo.ID = $ogpo.DisplayName }\n    }\n     format-table -inputobject $hash -autosize\n  } #end else\n<\/pre>\n<p>The complete <b>Get-GPO<\/b> function is seen&nbsp;here:<\/p>\n<pre class=\"codeSample\">Function Get-GPO()\n{\n New-Line(\"Listing GPOs from $domain\")\n $gpm=New-Object -ComObject gpmgmt.gpm\n $constants = $gpm.GetConstants()\n $gpmDomain = $gpm.GetDomain($domain,$null,$constants.useanydc)\n $gpmSearchCriteria = $gpm.CreateSearchCriteria()\n $gpo=$gpmdomain.SearchGPOs($gpmSearchCriteria)\n if($verbose)\n  {\n   $gpo\n  }\n ELSE\n  {\n   foreach($ogpo in $gpo)\n    {\n     $hash += @{ $ogpo.ID = $ogpo.DisplayName }\n    }\n     format-table -inputobject $hash -autosize\n  } #end else\n exit\n} #end Get-GPO\n<\/pre>\n<p>When the script is run, it produces an output similar to what you see here: <\/p>\n<p><img decoding=\"async\" height=\"356\" alt=\"Image of the output produced by the script\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/february\/hey0209\/hsg-02-9-9-01.jpg\" width=\"500\" border=\"0\"><\/p>\n<p>&nbsp;<\/p>\n<p>Well, LW, that is it for gathering a listing of all the GPOs that are defined in the domain. Join us tomorrow as Group Policy Week continues, when we will look at finding unlinked GPOs. 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! Do you ever wonder how some people ever get their jobs? We had a guy who was hired to organize our Group Policy implementation. The person was a loser. I mean, I do not think he could even spell Group Policy. Needless to say, the whole thing has morphed into some kind [&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-54433","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! Do you ever wonder how some people ever get their jobs? We had a guy who was hired to organize our Group Policy implementation. The person was a loser. I mean, I do not think he could even spell Group Policy. Needless to say, the whole thing has morphed into some kind [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54433","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=54433"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54433\/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=54433"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=54433"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=54433"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}