Você está na página 1de 6

Windows administration

At a glance:
What is Windows
PowerShell?
How GPOs were managed
previously
Migrating scripts to
Windows PowerShell

Simplify Group Policy


administration with
Windows PowerShell
Thorbjrn Sjvold

Microsoft Group Policy is the management backbone of nearly every


organisation with a Windows infrastructure.
technology didnt I have a feeling this is exactly what will hap
pen with Windows PowerShell , the latest

catch on overnight management technology from Microsoft. In


fact, Windows PowerShell is likely to make
it was somewhat your job as a Group Policy administrator sig
nificantly easier.
difficult to understand In this article, I show how the Micro
soft Group Policy Management Console
and required that you (GPMC) APIs written for Windows Script
ing Host languages like VBScript (and COM-
adopt Active Directory, based scripting languages in general) can be
consumed directly from Windows Power
a strange, new service Shell to simplify the way you manage Group
Policy in your environment.
that looked nothing like
Scripting Group Policy tasks
the Account/Resource When Microsoft released GPMC a few years
ago, Group Policy administrators sudden
domains that were the ly had a number of handy features at their
disposal. In particular, the Group-Policy-fo
standard at the time. cused MMC snap-in represented a huge step
forward for Group Policy management, es
Today, Group Policy pecially compared to Active Directory Users

TechNet Magazine July 2007 69

69_74_GPPowerShell_desfin.indd 69 8/6/07 11:22:14


Windows administration

and Computers. Moreover, there was a brand commands. In addition, Windows PowerShell
new API that let administrators use COM- has functions that work much like subrou
based languages such as VBScript to perform tines in VBScript, and that can be created in
Group Policy administration of tasks, such real time at the Windows PowerShell com
as backing up and restoring Group Policy mand prompt.
Objects (GPOs), migrating GPOs between Even better, Windows PowerShell is built
on the Microsoft .NET Framework, while
VBScript relies on older COM technology.
The vast amount of .NET This means that the vast amount of .NET
code being produced today can be used di
code being produced today rectly from within Windows PowerShell.
What it comes down to is that with Win
can be used directly from dows PowerShell, you get full scripting sup
port and interactive mode, all in one package.
within Windows PowerShell The examples I provide here will all be com
mand-line input so you can type as you read;
however, theyll work equally well if you put
domains, configuring security settings on them in a Windows PowerShell script file
GPOs and links, and reporting. and run it.
Unfortunately, GPMC did not provide the
ability to edit the actual configured settings Recreate old scripts using Windows
inside the GPOs. In other words, you could PowerShell
perform operations on the GPO container, The last thing you want to do when you start
such as reading GPO versions, reading mod with a new technology is toss out all your
ify dates, creating brand new GPOs, backing previous work. There are three approach
up and restoring/importing GPOs from dif es you can use to access COM objects from
ferent domains, and so forth, but you couldnt the GPMC API, or basically to reuse any old
programmatically add or change the content VBScript out there. You can select one of
of the GPO, for example adding a new redi these three options:
rected folder or a new software installation. Create a Windows PowerShell cmdlet us
What you generally did instead was create ing a programming language like C# or
the GPO and configure all settings manu managed C++.
ally using the Group Policy Object Editor, Use Windows PowerShell to access the
then back it up and import it into a test ScriptControl in MSScript.ocx to wrap
environment. When everything was verified old scripts.
and working properly, you would import Wrap the COM calls in reusable Windows
it into the live environment. Despite the PowerShell functions or else call the COM
missing feature, the use of scripts instead objects directly.
of manual interaction with the GPMC API
resulted in a tremendous amount of time, Im going to focus mainly on the third op
effort and error saved in day-to-day Group tion, but lets have a quick look at all the op
Policy administration. tions first.

The next level Creating a Windows PowerShell Cmdlet


How is Windows PowerShell different from Microsoft included a large number of cmd
scripting languages like VBScript? For start lets with Windows PowerShell, allowing you
ers, Windows PowerShell is a shell and, at to copy files, format output, retrieve the date
least for our purposes, you can think of a and time, and so on, but you can create your
shell as a command-line interpreter. Though own cmdlets as well. The process is fully doc
VBScript can be run from the command line, umented at www.microsoft.com/uk/tech
a VBScript file cannot be run line by line. A netmagazine/cmdlet. Here are the steps:
Windows PowerShell script, in contrast, can Create a class library DLL in a .NET pro
be created on the fly as a series of individual gramming language such as C#.

70 To get your FREE copy of TechNet Magazine subscribe at: www.microsoft.com/uk/technetmagazine

69_74_GPPowerShell_desfin.indd 70 8/6/07 11:22:15


Create a new class and inherit from the its a FileInfo object that can be used to get
base class cmdlet. the size of the file:
Set attributes that determine the name, $netObject = New-Object System.IO.FileInfo(
usage, input parameters, and so forth, and C:\boot.ini) # Create an instance of FileInfo
# representing c:\boot.ini
add your code.
Note that # is used in Windows PowerShell
Because Windows PowerShell is built on
for inline comments. Using this newly in
the .NET Framework, any types, such as a
stantiated FileInfo object, you can easily get
string, object, and so forth, that are being re
the size of boot.ini by simply typing the fol
turned or passed as parameters are exactly the
lowing code:
same in the code as in Windows PowerShell;
$netObject.Length # Display the size in bytes of the
no special type conversion is needed. # file in the command line interface
The real power of this solution is that you
have a complete programming language at Wait, werent we supposed to talk about
your disposal. COM objects and VBScript conversion? Yes,
but look at the following command:
Wrapping old scripts using the $comFileSystemObject = New-Object ComObject
Scripting.FileSystemObject
ScriptControl object in MSScript.ocx
Obviously, you need the VBScript engine to Youll notice that the syntax is basically the
run a VBScript file. What is not so obvious is same as I used previously to create native ob
that this engine is a COM object and, since jects from the .NET Framework, with two
you can use COM objects from Windows differences. First, I added the ComObject
PowerShell, you can invoke the VBScript en switch that points Windows PowerShell to
gine. Heres how this could look: ward the COM world instead of the .NET
world. Second, I use a COM ProgID instead
$scriptControl = New-Object -ComObject ScriptControl
$scriptControl.Language = VBScript
$scriptControl.AddCode(
Function ShowMessage(messageToDisplay)
MsgBox messageToDisplay
End Function) Figure 1 Custom functions in the download
$scriptControl.ExecuteStatement(ShowMessage
Hello World) Function Name Description

BackupAllGpos Backs up all GPOs in a domain


If you enter this code in the Windows
PowerShell Command Line Interface (CLI), BackupGpo Backs up a single GPO

the VBScript function ShowMessage is RestoreAllGpos Restores all GPOs from a backup to a domain
called and executed with a parameter, result
RestoreGpo Restores a single GPO from a backup
ing in a Message Box displayed with the text
Hello World. GetAllBackedUpGpos Retrieves the latest version of GPO backups from
a given path
Now some of you might think, Great!
Ive mastered the art of using COM from CopyGpo Copies the settings in a GPO to another GPO

Windows PowerShell and I can stop reading CreateGpo Creates a new empty GPO
this article and start filling the ScriptControl
DeleteGpo Deletes a GPO
object with my collection of old GPMC
scripts. Unfortunately, thats not the case. FindDisabledGpos Returns all GPOs where both the user and com-
puter part are disabled
This technique quickly becomes very com
plex and tough to debug as soon as the scripts FindUnlinkedGpos Returns all GPOs that have no links

get larger. CreateReportForGpo Creates an XML report for a single GPO in a


domain

Wrapping COM objects CreateReportForAllGpos Creates a separate XML report for each GPO in a
So the best option is the third: wrapping domain

the COM calls in reusable Windows Power GetGpoByNameOrID Finds a GPO by its display name or GPO ID
Shell functions, which lets you consume the GetBackupByNameOrId Finds a GPO backup by its display name or GPO
COM objects in the GPMC API. The line be ID
low shows how to create a .NET object di GetAllGposInDomain Returns all GPOs in a domain
rectly in Windows PowerShell. In this case,

TechNet Magazine July 2007 71

69_74_GPPowerShell_desfin.indd 71 8/6/07 11:22:15


Windows administration

Wrap the of a .NET constructor, in this case Scripting.


FileSystemObject. The ProgID is the same
PowerShell, but youll find a full set of Win
dows PowerShell functions to manage

COM calls name youve always used. In VBScript, the


equivalent would be:
Group Policy in the code download related
to this article, online at technetmagazine.

in reusable Set comFileSystemObject = CreateObject(


Scripting.FileSystemObject)
com/code07.aspx. Figure 1 lists the func
tions included in the download.

Windows To get the file size using VBScript, add the


line above to a file, together with the follow
As you read this section, feel free to start
the Windows PowerShell command line

PowerShell ing code:


Set comFileObject = comFileSystemObject.GetFile(
and type in the commands. Remember that
some commands are dependent on previ

functions
C:\Boot.ini)
WScript.Echo comFileObject.Size
ous commands, however. In other words,
some of the objects created initially will be
Then run it using Cscript.exe, for example.
used later on, so stay in the same Windows
In Windows PowerShell, you would do it like
PowerShell session. If you close the session,
this (directly from the Windows PowerShell
youll have to start again from the begin
command line if you like):
ning, retyping all the commands.
$comFileObject = $comFileSystemObject.GetFile(
C:\boot.ini) So, lets create a new GPO using Windows
$comFileObject.Size PowerShell. The Group Policy team at Mi
Of course, to convert a VBScript that reads crosoft included a number of fully work
the size of a file, I could have used the Win ing VBScript samples with GPMC that you
dows PowerShell cmdlet that manages ob can take advantage of to speed things up.
jects in drives, but I wanted to show you how Theyre in the %ProgramFiles%\GPMC\
easy it is to access COM from Windows Pow Scripts directory, where youll also find a file
erShell. Note that though I tell Windows called gpmc.chm that contains the GPMC
PowerShell to create a COM object, the ob API documentation. Lets have a look at the
ject that actually gets created, $comFileSys CreateGPO.wsf script and dissect it to see
temObject here, is a .NET object that wraps what makes it tick.
the COM object and exposes its interface. Near the top youll see this line:
In the scope of this article, however, that Dim GPM
Set GPM = CreateObject(GPMgmt.GPM)
doesnt really matter.
This is basically the starting point of any
Windows PowerShell in action Group Policy management session or script
Now that youve seen how to access COM because it instantiates the GPMgmt.GPM
from Windows PowerShell, lets focus on class that allows access to most of the GPMC
Group Policy. The examples here will show functionality. Lets go ahead and do this from
short code snippets to give you an idea of Windows PowerShell instead:
how to use the GPMC APIs from Windows $gpm = New-Object -ComObject GPMgmt.GPM

Figure 2 Get-Member output

72 To get your FREE copy of TechNet Magazine subscribe at: www.microsoft.com/uk/technetmagazine

69_74_GPPowerShell_desfin.indd 72 8/6/07 11:22:15


Now that you have the starting point for are created using methods that start with
Group Policy management, the next step this GPM object.
is to figure out what you can do with it. Lets continue now with the creation of a
Normally, youd turn to the documentation new GPO.
for this type of information, but Windows Figure 3 illustrates how simple it is to cre
PowerShell has a really cool feature. If you ate a GPO. Note that Ive left out some code,
type the following line, you get the output including error handling (for example, what
shown in Figure 2: will happen if you are not allowed to create
GPOs), and Ive hardcoded a domain name,
$gpm | gm
but you should get the idea.
Pretty cool if you ask me. Note how the Now that you know how to create a GPO,
Get-Member (or gm) cmdlet lets you see the lets open an existing one instead. You still have
properties and methods the object supports the reference to the domain, $gpmDomain, so
right from the command line. Of course its type in the following:
not the same as reading the documentation,
$gpmExistingGpo = $gpmDomain.GetGPO(
but it makes it easy to use objects youre al {31B2F340-016D-11D2-945F-00C04FB984F9})
# Open an existing GPO based on its GUID,
ready familiar with when you dont remem # in this case the Default Domain Policy.
ber the exact number of parameters, the $gpmExistingGpo.DisplayName
# Show the display name of the GPO, it
exact name, and so forth. One important # should say Default Domain Policy
point to note is that when you look at the $gpmExistingGpo.GenerateReportToFile($gpmConstants.
ReportHTML, .\DefaultDomainPolicyReport.html
GPMC documentation node listings, it looks
like the GPM object and all the other classes This gives you a full HTML report of the
are prefixed with the letter I; this is due to settings in the Default Domain Policy, but
the internal workings of COM and doesnt you can obviously use any of the meth
really concern us here; it is intended for C++ ods and properties, like ModificationTime,
programmers writing native COM code and which tells you when the GPO was last mod
denotes the difference between an interface ified, to figure out when any of the settings
and the class that implements it. Also note in the GPO changed.
that when using the GPMC APIs, there is This is extremely useful. Most likely youve
only one object you need created this way, been in a situation where the phones start
and that is GPMgmt.GPM; all other objects ringing like crazy with users complaining
that their computers are acting weird. You
suspect this is related to a changed, added
or deleted GPO setting, but you dont have
Figure 3 Create a GPO a clue which GPO to look in. Windows
PowerShell to the rescue! If you enter the
$gpmConstants = $gpm.GetConstants()
# This is the GPMC way to retrieve all script shown in Figure 4 at the Windows
# constants
$gpmDomain =$gpm.GetDomain(Mydomain.local, , $gpmConstants.UseAnyDC)
PowerShell command line, you get all GPOs
# Connects to the domain where the GPO should that have been changed in the last 24 hours.
# be created, replace Mydomain.local with the
# name of the domain to connect to. Note the ge operator, which means great
$gpmNewGpo = $gpmDomain.CreateGPO() er than or equal to. It might look strange if
# Create the GPO
$gpmNewGpo.DisplayName = My New Windows PowerShell GPO youre used to the < and > operators in oth
# Set the name of the GPO
er scripting or programming languages. But
those operators are used for redirection, for
example to redirect the output to file, and
Figure 4 Discovering modified GPOs thus could not be used as comparison opera
$gpmSearchCriteria = $gpm.CreateSearchCriteria()
tors in Windows PowerShell.
# We want all GPOs so no search criteria will be specified
$gpmAllGpos = $gpmDomain.SearchGPOs($gpmSearchCriteria)
# Find all GPOs in the domain Wrapping up
foreach ($gpmGpo in $gpmAllGpos) The code in Figure 5 lists the full script for
{
if ($gpmGpo.ModificationTime -ge (get-date).AddDays(-1)) {$gpmGpo.DisplayName} copying the settings in one GPO to anoth
# Check if the GPO has been modified less than 24 hours from now er GPO. You should now have a good idea
}
of how you can use this new technology

TechNet Magazine July 2007 73

69_74_GPPowerShell_desfin.indd 73 8/6/07 11:22:16


Windows administration

Figure 5 Copy the settings in one GPO to another GPO


###########################################################################
# Function : CopyGpo
# Description: Copies the settings in a GPO to another GPO
# Parameters : $sourceGpo - The GPO name or GPO ID of the GPO to copy
# : $sourceDomain - The dns name, such as microsoft.com, ofthedomain where the original GPO is located
# : $targetGpo - The GPO name of the GPO to add
# : $targetDomain - The dns name, such as microsoft.com, of the domain where the copy should be put
# : $migrationTable - The path to an optional Migration table to use when copying the GPO
# Returns : N/A
# Dependencies: Uses GetGpoByNameOrID, found in article download
###########################################################################
function CopyGpo(
[string] $sourceGpo=$(throw $sourceGpo is required),
[string] $sourceDomain=$(throw $sourceDomain is required),
[string] $targetGpo=$(throw $targetGpo is required),
[string] $targetDomain=$(throw $targetDomain is required),
[string] $migrationTable=$(),
[switch] $copyAcl)
{

$gpm = New-Object -ComObject GPMgmt.GPM # Create the GPMC Main object


$gpmConstants = $gpm.GetConstants() # Load the GPMC constants
$gpmSourceDomain = $gpm.GetDomain($sourceDomain, , $gpmConstants.UseAnyDC) # Connect to the domain passed
# using any DC
$gpmSourceGpo = GetGpoByNameOrID $sourceGpo $gpmSourceDomain
# Handle situations where no or multiple GPOs was found
switch ($gpmSourceGpo.Count)
{
{$_ -eq 0} {throw No GPO named $gpoName found; return}
{$_ -gt 1} {throw More than one GPO named $gpoName found; return}
}
if ($migrationTable)
{
$gpmMigrationTable = $gpm.GetMigrationTable($migrationTable)
}

$gpmTargetDomain = $gpm.GetDomain($targetDomain, , $gpmConstants.UseAnyDC) # Connect to the domain passed


# using any DC

$copyFlags = 0
if ($copyAcl)
{
$copyFlags = Constants.ProcessSecurity
}
$gpmResult = $gpmSourceGpo.CopyTo($copyFlags, $gpmTargetDomain, $targetGpo)
[void] $gpmResult.OverallStatus

with Group Policy and how you can reuse the equivalent in VBScript. Youll find it at
any COM object or VBScript code that con microsoft.com/technet/scriptcenter/topics/
sumes a COM object. winpsh/convert.
Windows PowerShell will be, just as Group In addition, the GPMC API is fully docu
Policy already is, a natural part of any Win mented; you can download the information
dows management environment. But there from the Group Policy site at microsoft.com/
are millions of lines of VBScript out there grouppolicy.
that will have to be migrated or maintained, Last but not least, if you havent already
and hopefully this tutorial will help. installed Windows PowerShell, what are
There are a number of sources you can you waiting for? Download it from micro
use to enhance your Group Policy adminis soft.com/powershell. Have fun.
tration and other areas where youve previ
ously used VBScript, including the Windows Thorbjrn Sjvold is the CTO and
PowerShell functions in the download, and a founder of Special Operations Software
great VBScript-to-Windows PowerShell con (www.specopssoft.com), a provider of Group
version guide on the TechNet Web site that Policy based Systems Management and
provides hints on how to do common tasks Security extension products. Reach him at
in Windows PowerShell when you know thorbjorn.sjovold@specopssoft.com.

74 To get your FREE copy of TechNet Magazine subscribe at: www.microsoft.com/uk/technetmagazine

69_74_GPPowerShell_desfin.indd 74 8/6/07 11:22:16

Você também pode gostar