Hey, Scripting Guy! Good morning. We are in the process of modifying our Group Policy implementation, and I anticipate having to create 15 or so new Group Policy objects. I know that I can open the Group Policy Management Console, right-click, and go through the wizard, but I would prefer to have a script that would create the Group Policy objects for me. Can this be done?
– CC
Hi CC,
The good news is that we can do exactly what you asked. We can create new Group Policy objects from a script. The bad news is that we cannot do what you probably wanted to do, and that is to create a Group Policy object that does anything. There are third-party tools that will allow you to both create and configure Group Policy objects via script. In Windows 2008 R2, there are some pretty cool Group Policy cmdlets that provide additional capabilities. Without access to either of those solutions, you can create a Group Policy object via script and configure it later—so it helps.
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. |
The script that will create a GPO is called, surprisingly enough, CreateGPO.ps1.
CreateGPO.ps1
param( $domain = $env:userDNSdomain, $gpoName = ($paramMissing=$true), [switch]$whatif, [switch]$help, [switch]$examples, [switch]$min, [switch]$full ) #end param # Begin Functions function Get-HelpTopic() { $descriptionText= ` @" NAME: CreateGPO.ps1 DESCRIPTION: Creates a new GPO in a specified Domain by using default settings. This GPO can then easily be modified by using the GPMC This script supports prototyping by using the -whatif switch. PARAMETERS: -Domain domain to create the new GPO -gpoName name of the GPO to create -whatif prototypes the command -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: CreateGPO.ps1 Displays an error missing parameter, and calls help CreateGPO.ps1 -gpoName "SetScreenSaverTimeout" Creates a GPO named SetScreenSaverTimeout in the local domain using the default GPO settings CreateGPO.ps1 -gpoName "SetScreenSaverTimeout" -domain "nwtraders.com Creates a GPO named SetScreenSaverTimeout in the nwtraders.com domain CreateGPO.ps1 -gpoName "SetScreenSaverTimeout" -domain "nwtraders.com -whatif Displays what if: Perform operation create GPO SetScreenSaverTimeout in domain nwtraders.com CreateGPO.ps1 -help Prints the help topic for the script CreateGPO.ps1 -help -full Prints full help topic for the script CreateGPO.ps1 -help -examples Prints only the examples for the script CreateGPO.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-Whatif() { "what if: Perform operation create GPO $gpoName in domain $domain" exit } #end Get-Whatif Function New-GPO() { $error.clear() $gpm = new-object -comobject GPMgmt.gpm $constants = $gpm.getConstants() $gpmDomain = $gpm.getDomain($domain,$null, $constants.UseAnyDC) $gpmGPO = $gpmDomain.CreateGPO() $gpmGPO.DisplayName = $gpoName if($error.count -ne 0) { $GPMGPO.Delete() New-Line -strIN "An error occurred creating $gpoName" -scolor red "The error was $($error.categoryInfo)" } else { Write-host "Created GPO $($gpmGPO.displayname)" } } #end New-GPO # Entry Point if($help) { Get-HelpTopic } if($examples) { Get-HelpTopic } if($full) { Get-HelpTopic } if($whatif) { Get-Whatif } if($paramMissing) { "GPO name is required" ; Get-HelpTopic } if($gpoName) { New-GPO }
The CreateGPO.ps1 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 and the help function.
After we get past the command-line parameters and the help function, the next function to talk about is the Get-Whatif function, which tells us what the script will do after you have configured the parameters. An example of running the script with whatif is seen here:
CreateGPO.ps1 -gpoName "SetScreenSaverTimeout" -domain "nwtraders.com –whatif
When the above command is typed, it displays what if: Perform operation create GPO SetScreenSaverTimeout in domain nwtraders.com. This is useful not only because it will give you confidence about what the command will actually do, but also because it will give troubleshooting help. This is because it lets you know which values have been received for which parameters. The Get-Whatif function basically prints out a string and the values that are supplied to the $gpoName variable and the $domain variable. Both of these variables obtain their value from the command line when the script is launched; however,. by default the $domain variable is obtained by reading the environmental variable userDNSDomain off the environmental drive. The Get-Whatif function is seen here:
Function Get-Whatif() { "what if: Perform operation create GPO $gpoName in domain $domain" exit } #end Get-Whatif
The main portion of the script is the New-GPO function. The first thing we do is create an instance of the GPMgmt.gpm object. We can use this object if the Group Policy Management Console is installed. For Windows Vista with SP1, you will need to install RSAT. Here is the line of code that creates the GPMgmt.gpm object:
$gpm = new-object -comobject GPMgmt.gpm
The next thing we need to do is to use the GetConstants method, which returns the constants and their associated values to use with the GPMgmt.gpm object. All the constants and their values are seen in Table 1.
Table 1 Group Policy Management API constant values | |
Constant | Value |
permGPOApply |
65536 |
permGPORead |
65792 |
permGPOEdit |
65793 |
permGPOEditSecurityAndDelete |
65794 |
permGPOCustom |
65794 |
permWMIFilterEdit |
131072 |
permWMIFilterFullControl |
131073 |
permWMIFilterCustom |
131074 |
permSOMLink |
1835008 |
permSOMLogging |
1573120 |
permSOMPlanning |
1573376 |
permSOMGPOCreate |
1049600 |
permSOMWMICreate |
1049344 |
permSOMWMIFullControl |
1049345 |
SearchPropertyGPOPermissions |
0 |
SearchPropertyGPOEffectivePermissions |
1 |
SearchPropertyGPODisplayName |
2 |
SearchPropertyGPOWMIFilter |
3 |
SearchPropertyGPOID |
4 |
SearchPropertyGPOComputerExtensions |
5 |
SearchPropertyGPOUserExtensions |
6 |
SearchPropertySOMLinks |
7 |
SearchPropertyGPODomain |
8 |
SearchPropertyBackupMostRecent |
9 |
SearchOpEquals |
0 |
SearchOpContains |
1 |
SearchOpNotContains |
2 |
SearchOpNotEquals |
3 |
UsePDC |
0 |
UseAnyDC |
1 |
DoNotUseW2KDC |
2 |
somSite |
0 |
somDomain |
1 |
somOU |
2 |
DoNotValidateDC |
1 |
ReportHTML |
1 |
ReportXML |
0 |
RSOPModeUnknown |
0 |
RSOPModePlanning |
1 |
RSOPModeLogging |
2 |
EntryTypeUser |
0 |
EntryTypeComputer |
1 |
EntryTypeLocalGroup |
2 |
EntryTypeGlobalGroup |
3 |
EntryTypeUniversalGroup |
4 |
EntryTypeUNCPath |
5 |
EntryTypeUnknown |
6 |
DestinationOptionSameAsSource |
0 |
DestinationOptionNone |
1 |
DestinationOptionByRelativeName |
2 |
DestinationOptionSet |
3 |
MigrationTableOnly |
1 |
ProcessSecurity |
2 |
RsopLoggingNoComputer |
65536 |
RsopLoggingNoUser |
131072 |
RsopPlanningAssumeSlowLink |
1 |
RsopPlanningAssumeUserWQLFilterTrue |
8 |
RsopPlanningAssumeCompWQLFilterTrue |
16 |
BackupTypeGPO |
0 |
BackupTypeStarterGPO |
1 |
StarterGPOTypeSystem |
0 |
StarterGPOTypeCustom |
1 |
SearchPropertyStarterGPOPermissions |
10 |
SearchPropertyStarterGPOEffectivePermissions |
11 |
SearchPropertyStarterGPODisplayName |
12 |
SearchPropertyStarterGPOID |
13 |
SearchPropertyStarterGPODomain |
14 |
permStarterGPORead |
197888 |
permStarterGPOEdit |
197889 |
permStarterGPOFullControl |
197890 |
permStarterGPOCustom |
197891 |
ReportLegacy |
0 |
ReportComments |
1 |
After we have created the constants and stored them in a variable, we can use them directly when we obtain a connection to the domain. This is seen here:
$constants = $gpm.getConstants() $gpmDomain = $gpm.getDomain($domain,$null, $constants.UseAnyDC)
After we have connected to the domain, we use the CreateGPO method to create a Group Policy object. And after we have created the GPO, we need to specify the display name for it:
$gpmGPO = $gpmDomain.CreateGPO() $gpmGPO.DisplayName = $gpoName
Because we are creating a new GPO, we might be interested in seeing if it was actually created. To do this, we check the error count. If the error count is not equal to 0, a problem occurred and we delete the GPO. Otherwise, the operation was successful and everything is groovy. This is seen here:
if($error.count -ne 0) { $GPMGPO.Delete() New-Line -strIN "An error occurred creating $gpoName" -scolor red "The error was $($error.categoryInfo)" } else { Write-host "Created GPO $($gpmGPO.displayname)" } } #end New-GPO
Well, CC, that is the good news when it comes to creating GPOs: you can do it via scripting. Hope this helps, and that it saves you some time and effort in your new Group Policy plan. Join us tomorrow when we will talk about finding GPOs that have no security filtering applied. See you then.
Ed Wilson and Craig Liebendorfer, Scripting Guys
0 comments