Hey, Scripting Guy! How Can I Generate a List of My Group Policy Objects?


Hey, Scripting Guy! Question


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?

- JG

SpacerHey, Scripting Guy! Answer

Hi JG,


"That dog won't hunt." 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 haintnarynone, which is a reply to the question, "Do you have any more milk?" When you pronounce haintnarynone , 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 “haintnarynone.” However, I digress. (Let it never be said that a Scripting Guy became distracted during the process of writing a “Hey, Scripting Guy!” article. Well, okay, maybe once in a while: A quick search of the Script Center for the word “distracted” returns eight hits. So 9 times we became distracted. We’ll take that average.)


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't hunt. Sorry. I don’t really know much about dogs at all, so let's talk about Group Policy scripting instead.







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 Script Center Script Repository, and in the Community-Submitted Scripts Center. You can also download a collection of sample Group Policy management scripts.



To find Group Policy objects that do not have any security filtering associated with them, you can use the FindGPOsWithNoSecurityFiltering.ps1 script which is seen here. To obtain help on the script you can use the following syntax:

FindGPOsWithNoSecurityFiltering.ps1 –help

FindGPOsWithNoSecurityFiltering.ps1

param(
$domain=$env:userDNSdomain,
[switch]$query,
[switch]$help,
[switch]$examples,
[switch]$min,
[switch]$full
) #end param

# Begin Functions

function Get-HelpTopic()
{
$descriptionText= `
@"
NAME: FindGPOsWithNoSecurityFiltering.ps1
DESCRIPTION:
Finds GPOs that have no security filtering
assigned, and therefore they apply to no one

PARAMETERS:
-domain domain to query for orphaned gpos
-query causes query to execute
-help prints help description and parameters file
-examples prints only help examples of syntax
-full prints complete help information
-min prints minimal help. Modifies -help

"@ #end descriptionText

$examplesText= `
@"

SYNTAX:
FindGPOsWithNoSecurityFiltering.ps1

Displays an error missing query, and calls help

FindGPOsWithNoSecurityFiltering.ps1 -query

Queries current domain for GPOs with no security
filter applied to them

FindGPOsWithNoSecurityFiltering.ps1 -domain nwtraders.com -query

Queries nwtraders.com domain for GPOs with no security
filter applied to them

FindGPOsWithNoSecurityFiltering.ps1 -help

Prints the help topic for the script

FindGPOsWithNoSecurityFiltering.ps1 -help -full

Prints full help topic for the script

FindGPOsWithNoSecurityFiltering.ps1 -help -examples

Prints only the examples for the script

FindGPOsWithNoSecurityFiltering.ps1 -examples

Prints only the examples for the script
"@ #end examplesText

$remarks = `
"
REMARKS
For more information, type: $($MyInvocation.ScriptName) -help -full
" #end remarks

if($examples) { $examplesText ; $remarks ; exit }
if($full) { $descriptionText; $examplesText ; exit }
if($min) { $descriptionText ; exit }
$descriptionText; $remarks
exit
} #end Get-HelpTopic function

function New-Line (
$strIN,
$char = "=",
$sColor = "Yellow",
$uColor = "darkYellow",
[switch]$help
)
{
if($help)
{
$local:helpText = `
@"
New-Line accepts inputs: -strIN for input string and -char for seperator
-sColor for the string color, and -uColor for the underline color. Only
the -strIn is required. The others have the following default values:
-char: =, -sColor: Yellow, -uColor: darkYellow
Example:
New-Line -strIN "Hello world"
New-Line -strIn "Morgen welt" -char "-" -sColor "blue" -uColor "yellow"
New-Line -help
"@
$local:helpText
break
} #end New-Line help

$strLine= $char * $strIn.length
Write-Host -ForegroundColor $sColor $strIN
Write-Host -ForegroundColor $uColor $strLine
} #end New-Line function

Function Get-NoFilter()
{
$gpm = new-object -comobject gpmGMT.gpm
$constants = $gpm.getConstants()
$gpmDomain = $gpm.GetDomain($domain,$null,$constants.useanydc)
$gpmSearchCriteria = $gpm.CreateSearchCriteria()
$gpoList = $gpmDomain.SearchGpos($gpmSearchCriteria)
$perm = $Constants.PermGPOApply
foreach($gpo in $gpoList)
{
$secInfo = $gpo.GetSecurityInfo()
foreach($secPerm in $secInfo)
{
if($secPerm.Permission -ne $perm)
{
$errorActionPreference = "SilentlyContinue"
$hash += @{ $gpo.id = $gpo.DisplayName }
$errorActionPreference = "continue"
} #end if
} #end foreach
} #end foreach
New-Line("No permissions were found $($hash.count) GPOs")
format-table -inputobject $hash -autosize
exit
} #end Get-NoFilter

# Entry Point

if($help) { Get-HelpTopic }
if($examples) { Get-HelpTopic }
if($full) { Get-HelpTopic }
if($query) { Get-NoFilter }
if(!$query) { "missing query .. " ; Get-HelpTopic }


 


The FindGPOsWithNoSecurityFiltering.ps1 script is written in the same style as the other GPO scripts we have seen this week. Please refer to the articles from Monday and Tuesday to see information about the command-line parameters, the help function, and the New-Line function.



The core script functionality is the Get-NoFilter 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 gpmGMT.gpm object. Because the object is a COM object we use the –comobject parameter of the New-Object cmdlet. We store the returned object in the $gpm variable as seen here:

$gpm = new-object -comobject gpmGMT.gpm

After we have created the gpmGMT.gpm object, we have access to the methods seen in Table 1.


































































Table 1 Methods of the GpmGMT.gpm object





Name *





MemberType *





Definition *

CreateMigrationTable


Method


IGPMMigrationTable CreateMigrationTable ()


CreatePermission


Method


IGPMPermission CreatePermission (string, GPMPermissionType, bool)


CreateSearchCriteria


Method


IGPMSearchCriteria CreateSearchCriteria ()


CreateTrustee


Method


IGPMTrustee CreateTrustee (string)


GetBackupDir


Method


IGPMBackupDir GetBackupDir (string)


GetBackupDirEx


Method


IGPMBackupDirEx GetBackupDirEx (string, GPMBackupType)


GetClientSideExtensions


Method


IGPMCSECollection GetClientSideExtensions ()


GetConstants


Method


IGPMConstants GetConstants ()


GetDomain


Method


IGPMDomain GetDomain (string, string, int)


GetMigrationTable


Method


IGPMMigrationTable GetMigrationTable (string)


GetRSOP


Method


IGPMRSOP GetRSOP (GPMRSOPMode, string, int)


GetSitesContainer


Method


IGPMSitesContainer GetSitesContainer (string, string, string, int)


InitializeReporting


Method


void InitializeReporting (string)


InitializeReporting


Method


void InitializeReportingEx (string, int)



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 Wednesday’s “Hey, Scripting Guy!” article, and the process and purpose is exactly the same as what we do here:

$constants = $gpm.getConstants()

Now we need to connect to the domain. To do that, we use the GetDomain method and pass it the name of the domain and the useanydc constant. We store the returned object in the $gpmDomain variable. Next we need to create the search criteria. To do this, we use the CreateSearchCriteria method and store the returned search criteria in the $gpmSearchCriteria variable. We then use the SearchGpos method from the domain we stored in the $gpmDomain variable. We give the SearchGpos method the search criteria we created in the previous line. This is seen here:

$gpmDomain = $gpm.GetDomain($domain,$null,$constants.useanydc)
$gpmSearchCriteria = $gpm.CreateSearchCriteria()
$gpoList = $gpmDomain.SearchGpos($gpmSearchCriteria)

We now need to retrieve a specific constant from all the constants we have stored in the $constants variable. The specific one we need is called PermGPOApply, and it is used to specify that the GPO has permissions applied. This is seen here, where we store the resultant constant in the $perm variable:

$perm = $Constants.PermGPOApply

We are now ready to begin examining each of the GPOs. We first use the ForEach statement to work through each of the GPOs that is stored in the $gpoList variable. We take each one of the GPOs and call the GetSecurityInfo method to retrieve the security information that is associated with each of the GPOs. We store the security information in the $secInfo variable:

foreach($gpo in $gpoList)
{
$secInfo = $gpo.GetSecurityInfo()

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 PermGPOApply constant, we add the name of the GPO to the hash table we create with the name of $hash. A hash table is similar to the VBScript concept of a dictionary object. Before and after each attempt to obtain the display name, we use $errorActionPreference = "SilentlyContinue", which is the same as VBScript On Error Resume Next. By setting $errorActionPreference equal to "continue", in this case it is similar to using On Error Goto 0, which is discussed here.

foreach($secPerm in $secInfo)
{
if($secPerm.Permission -ne $perm)
{
$errorActionPreference = "SilentlyContinue"
$hash += @{ $gpo.id = $gpo.DisplayName }
$errorActionPreference = "continue"
} #end if
} #end foreach
} #end foreach

It is time to produce our report. We use the count property from the hashtable object to tell us how many GPOs were found without permissions. We then call the Format-Table cmdlet to print out the hash table:

New-Line("No permissions were found $($hash.count) GPOs")
format-table -inputobject $hash –autosize

 


Well, JG, I believe that "this dog will hunt!" 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'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 grab bag of questions. Until then, peace.


 


Ed Wilson and Craig Liebendorfer, Scripting Guys

Comments (0)

Skip to main content