Windows PowerShellAutomating Directory Management

Don Jones

One of the most unfortunate things about the first version of Windows PowerShell is its timing. The Windows PowerShell team was under a certain amount of pressure to ship the product (there was this little product called Exchange Server 2007 launching and that was depending on Windows PowerShell) and the Active

Directory team had a lot on its hands at the time (another little product called Windows Server® 2008 was also in the works). So Windows PowerShell shipped with less than superior Active Directory® management capabilities.

To be clear, Windows PowerShell® doesn't completely lack Active Directory features. In fact, the Windows PowerShell team made some heroic last-hour efforts to put in decent support for Active Directory Services Interface (ADSI), a scripting-friendly technology already well-known to users of VBScript.

The ADSI Way

ADSI is similar to Windows® Management Instrumentation (WMI) in the way it works. You issue a query, which is written using a special syntax. The query is transmitted to a remote computer (such as a domain controller) and then executed. The result of the query is an Active Directory object or collection of objects (such as a user or a group), and you get a reference to that object that you can then work with. You can modify properties of the object or execute methods to save your changes, create new objects, delete objects, and so forth. For example, to create a user, you query the organizational unit (OU) or container that you want the user to live in. The object you get back has a Create method, which can be used to create the user.

On a very basic level, using ADSI in Windows PowerShell appears simple and straightforward. For example, this command will retrieve a user and display his Company attribute:

$user = [ADSI]"LDAP://cn=Ringo,ou=Singers,dc=company,dc=pri"
$user.Get("Company")

You can pipe the user to Get-Member to see its properties and methods. Sadly, Windows PowerShell 1.0 doesn't really do a good job of implementing these directory objects. As Figure 1 shows, the shell doesn't enumerate the object's directory attributes, nor does it display the methods of the object—such as the Get method I used.

Figure 1 Piping the user to Get-Member to see its properties

Figure 1** Piping the user to Get-Member to see its properties **(Click the image for a larger view)

This support is somewhat improved in the Community Technology Preview (CTP) of Windows PowerShell 2.0, but only to a certain extent. The bottom line is that the underlying Microsoft® .NET Framework doesn't make it easy for administrators to see what they want—the Framework was, after all, originally designed for developers. The other problem is that the Windows PowerShell team can only do so much, and great Active Directory support needs to come from the folks who know directories best. In other words, the Active Directory team. I'm sure that will happen in time—after all, Windows PowerShell is still young. But what are you supposed to do in the meantime?

You may recall that I discussed using the ADSI technologies included in Windows PowerShell in the June 2007 installment of this column (technetmagazine.com/issues/2007/06/PowerShell). I suggest you go back and read that column if you want more details on that "native" technique. For this installment, I want to show you some other approaches.

A Rich Ecosystem

Windows PowerShell architect Jeffrey Snover often refers to the rich ecosystem surrounding Windows PowerShell. This simply means that the team did a great job of making sure anyone, not just programmers within Microsoft, can extend the capabilities of Windows PowerShell. A number of companies are already doing so by creating native Windows PowerShell cmdlets that allow you to administer their products from the command line—VMWare, IBM, Citrix, and Foundry are just a few of the major companies so far.

One of my favorite examples of this rich ecosystem is from Quest software. The company offers a set of free, noncommercial cmdlets designed for Active Directory management. You can download them from quest.com/powershell. They also offer PowerGUI (powergui.org), a free, noncommercial graphical UI that sits on top of Windows PowerShell for folks who aren't quite ready to commit to the full command-line experience yet. PowerGUI can make it easier to learn how to use the Active Directory management cmdlets. And believe me—you'll want to use them. These cmdlets give you an ease and power for Active Directory management that is simply unprecedented. (In case you want to read more about PowerGUI, it was actually included in the January 2008 installment of the Toolbox column, which you can find at technetmagazine.com/issues/2008/01/Toolbox.)

The Windows PowerShell Way

Anything involving cmdlets is truly the Windows PowerShell way of doing things. You don't have to deal with traditional-looking scripts or fancy programming objects. Here is my favorite one-liner in the universe. It's a single command line that imports a CSV file and uses the information in it to create dozens or even hundreds of new Active Directory users:

Import-CSV 'C:\provision1.csv' |
ForEach-Object {New-QADUser -organizationalUnit 'company.pri/Singers' -name ($_.'First Name' + '.' + $_.'Last Name') 
-samAccountName $_.'Logon name' -city $_.city -title $_.'Job title' -department $_.department} 

This is indeed a long command, but it's amazingly powerful. It starts with Import-CSV, a native shell cmdlet that simply reads a CSV file and returns objects. Each line in the CSV file is a single object, and the columns of the CSV file become properties of the object. In my Provision1.csv file, the column names are things like "Logon Name" and "First Name"—this is interesting because the column names don't map directly to Active Directory user attributes. I find that it's common for files like this to use more familiar-sounding column names instead of names that are specific to Active Directory. After all, you might be receiving this file from someone in your company's personnel department, and they're unlikely to know that the Last Name is really the sn attribute in Active Directory.

Once all of the data in the CSV file has been imported and also turned into objects, those objects are piped to the ForEach-Object cmdlet, which executes a block of code—inside the curly braces in my one-liner—for each object. That is, for each line in the CSV file, this script will execute once. Within the script, the special $_ variable is a reference to the current object—or, the current line of the CSV file.

You can see that for each object, I'm executing the New-QADUser cmdlet. That's one of the dozen or so cmdlets in the Quest add-in. The name QADUser is worth noting. The Q, as you might have guessed, stands for Quest. This naming convention is designed to avoid a conflict with the eventual New-ADUser cmdlet that the Microsoft Active Directory team will likely produce in the future. That way, if both cmdlets are loaded into the shell at the same time, both you and the shell will be able to tell them apart more easily.

The remainder of the one-liner consists of parameters for the New-QADUser cmdlet. It starts by specifying the organizationalUnit, which is where you want all of the new users to be created. Next is the name attribute, which I've set to be the contents of the First Name column, a period, and then the contents of the Last Name column.

One last interesting fact here: The city parameter will actually change the l attribute (or Locality-Name) in Active Directory. The cmdlet also accepts a parameter named l, which does the same thing. For the most part, parameters that refer to Active Directory attributes can use either the attribute name or the text label from the Active Directory Users & Computers tool.

The Other Windows PowerShell Way

Active Directory is a hierarchical store, and one of the strengths of Windows PowerShell is its ability to expose any hierarchical store as a disk drive, allowing you to use a familiar set of commands like Dir, Del, Ren, Copy, and so forth to manage a variety of stores. Unfortunately, Windows PowerShell 1.0 didn't ship with a PSDrive Provider for Active Directory, meaning the shell has no way to expose Active Directory itself as a drive.

Fortunately, that rich ecosystem comes back into play with the PowerShell Community Extensions. This is a free, open-source add-in available from codeplex.com/powershellcx. Once you have it installed, the PowerShell Community Extensions let you simply direct the shell to your domain name to begin managing the directory as if it were a drive:

CD COMPANY:
CD SINGERS
DIR

These commands will change to the COMPANY domain, change to the Singers OU, and then display a list of objects, as shown in Figure 2. From there I can use commands like Del to delete a user, Md to create a new OU, and so forth. There are a few catches in the Community Extensions PSDrive Provider. These essentially have to do with functionality that you might expect to be implemented, but isn't available because things don't map to the way Active Directory itself works. And you do have to be exceedingly careful: changing to the root of your domain and running del * -recurse will, in fact, delete every object in the domain, provided you have permission. It won't even ask "are you sure," by default. Yes, the command line is powerful, and with that power comes a risk for someone who isn't skilled and careful.

Figure 2 Using the PowerShell Community Extensions to direct the shell and manage the directory

Figure 2** Using the PowerShell Community Extensions to direct the shell and manage the directory **(Click the image for a larger view)

Start Using the Shell Today

Students in my classes always ask what they can do with Windows PowerShell today. After all, not every Microsoft product has been redesigned to use Windows PowerShell, and offhand you might think that Windows PowerShell is still waiting around for things to get really exciting.

The fact is, things are already exciting. Even though Microsoft hasn't yet instrumented Active Directory for command-line management, others have taken a stab at it and done quite well. You can use Windows PowerShell to perform many administrative tasks, including automating some of the most time-consuming and burdensome tasks, such as creating batches of new users. The trick is to discover some of the things that the community is doing to make Windows PowerShell more useful now. (You might want to explore PowerShellCommunity.org, a site co-sponsored by Microsoft that I help administer.) With the right tools loaded into Windows PowerShell, you can begin scripting some of the most time-consuming administrative tasks that you don't want to be doing, and start to become a more effective and efficient administrator.

Don Jones is the co-author of Windows PowerShell: TFM, 2nd Edition, author of VBScript, WMI, and ADSI Unleashed, and director of PowerShellCommunity.org.

© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; reproduction in part or in whole without permission is prohibited.