Creating objects at the command line
Performing bulk operations within Active Directory
Active Directory updates and maintenance
If you’ve ever been handed an Excel spreadsheet listing 200 new employees starting next week, or if your user accounts are configured incorrectly because help desk staff clicked something
they shouldn’t have, or if you just want an easier way to manage Active Directory® besides opening Users and Computers every time, there are a number of free administration tools that can help. Some are built right into the Windows® OS, some come in a Resource Kit or the Windows Support Tools, and some are free third-party tools. What are these handy tools and where can you get them? Let’s find out.
I’ll start with the built-in command-line tools in Windows Server® 2003 that allow you to create, delete, modify, and search for objects in Active Directory.
The Comma-Separated Values Data Exchange tool, known as CSVDE, allows you to import new objects into Active Directory using a CSV source file; it also provides you with the ability to export existing objects to a CSV file. CSVDE can’t be used to modify existing objects; when you are using this tool in import mode you can only create brand-new objects.
Exporting a list of existing objects with CSVDE is fairly simple. Here’s how you’d export your Active Directory objects to a file called ad.csv:
csvde –f ad.csv
The –f switch indicates that the name of the output file follows. But you must be aware of the fact that, depending on your environment, this basic syntax could result in a huge and unwieldy output file. To restrict the tool to export objects only within a particular organizational unit (OU), you could modify the statement as follows:
csvde –f UsersOU.csv –d ou=Users,dc=contoso,dc=com
Let’s further say that you’re only interested in exporting user objects into your CSV file. In that case, you can add the –r switch, which allows you to specify a Lightweight Directory Access Protocol (LDAP) filter for the search, and the –l switch, which restricts the number of attributes that are exported (note that the following is all on one line):
csvde –f UsersOnly.csv –d ou=Users,dc=contoso,dc=com –r "(&(objectcategory=person)(objectclass=user))" –l DN,objectClass,description
The –i switch allows you to import objects into Active Directory from a source CSV file. However, creating user objects with CSVDE has one critical limitation: you can’t set user passwords with it. Because of this, I’d avoid using CSVDE to create user objects.
Active Directory provides a second built-in tool for bulk user operations, called LDIFDE, and it is more powerful and flexible than CSVDE. In addition to creating new objects, LDIFDE can also modify and delete existing objects and even extend the Active Directory schema. The trade-off for LDIFDE’s flexibility is that the necessary input file, which is referred to as an LDIF file with the extension .ldf, uses a more complex format than the simple CSV file. (With a little work you can also configure user passwords, but I’ll get to that in a moment.)
Let’s start with a simple example, exporting users in an OU to an LDF file (note that the following is all on one line):
ldifde -f users.ldf -s DC1.contoso.com -d "ou=UsersOU,dc=contoso,dc=com" –r "(&(objectcategory=person)(objectclass=user))"
As with most command-line tools, you can find a full explanation of the LDIFDE switches by running the LDIFDE /? command. Figure 1 describes the ones I’ve used here. (Note that the switches are actually the same for both the CSVDE and LDIFDE commands.)
Figure 1 LDIFDE switches
|Specifies LDAP path that LDIFDE should connect to for the operation.
|Indicates the name of the file to be used, in this case to output the results of the export.
|Specifies the LDAP filter to use for an export.
|Specifies the domain controller (DC) to connect to that will perform the operation; if you leave this out, LDIFDE will connect to the local DC (or the DC that authenticated you if you are running the tool from a workstation).
The real power of LDIFDE is in creating and manipulating objects. Before doing this, however, you first need to create an input file. The following creates two new user accounts called afuller and rking; to create the input file, enter the text in Notepad (or your favorite plain-text editor) and save it as NewUsers.ldf:
dn: CN=afuller, OU=UsersOU, DC=contoso, DC=com changetype: add cn: afuller objectClass: user samAccountName: afuller dn: CN=rking, OU=UsersOU, DC=contoso, DC=com changetype: add cn: rking objectClass: user samAccountName: rking
Once you’ve finished creating the file, run the following command:
ldifde –i –f NewUsers.ldf –s DC1.contoso.com
The only new switch here is -i, which, you can probably guess for yourself, denotes that this is an import operation instead of an export.
When modifying or deleting existing objects, the syntax for the LDIFDE command doesn’t change; instead, you modify the contents of the LDF file. To change the description field of the user accounts, create a text file called ModifyUsers.ldf, such as the one shown in Figure 2.
Figure 2 The ModifyUsers LDF file (Click the image for a larger view)
You import the changes by running the same LDIFDE command syntax as before, specifying the new LDF file name after the -f switch. The LDF format for deleting objects is even simpler; to delete the users you’ve been working with, create a file called DeleteUsers.ldf and enter the following:
dn: CN=afuller OU=UsersOU, DC=contoso, DC=com changetype: delete dn: CN=rking, OU=UsersOU, DC=contoso, DC=com changetype: delete
Note that unlike CSVDE, LDIFDE is capable of configuring user passwords. Before you can configure the unicodePWD attribute for a user account, however, you must configure secure sockets layer/transport layer security (SSL/TLS) encryption on your domain controllers.
Moreover, LDIFDE can create and modify any type of Active Directory object, not just user accounts. The following LDF file, for example, will create a custom schema extension called EmployeeID-example in the schema of the contoso.com forest:
dn: cn=EmployeeID-example,cn=Schema, cn=Configuration,dc=contoso,dc=com changetype: add adminDisplayName: EmployeeID-Example attributeID: 184.108.40.206.220.127.116.11.7 attributeSyntax: 18.104.22.168 cn: Employee-ID instanceType: 4 isSingleValued: True lDAPDisplayName: employeeID-example
Because LDIFDE files use the industry-standard LDAP file format, third-party applications that need to modify the Active Directory schema will often supply LDF files you can use to examine and approve the changes before applying them to your production environment.
In addition to tools for bulk import and export operations, Windows Server 2003 also includes a built-in toolset that lets you create, delete, and modify various Active Directory objects as well as perform queries for objects that meet certain criteria. (Note that these tools, dsadd, dsrm, dsget, and dsquery, are not supported under Windows 2000 Active Directory.)
Dsadd is used to create an instance of an Active Directory object class on a particular directory partition. These classes include users, computers, contacts, groups, organizational units, and quotas. Dsadd has a generic syntax that consists of the following:
dsadd <ObjectType> <ObjectDistinguishedName> attributes
Note that each object type you create takes a specific set of switches corresponding to the attributes available for that type. This command creates a single user object with various attributes populated (note that the following is all on one line):
dsadd user cn=afuller,ou=IT,dc=contoso,dc=com –samID afuller –fn Andrew –ln Fuller –pwd * -memberOf cn=IT,ou=Groups,dc=contoso,dc=com "cn=Help Desk,ou=Groups, dc=contoso,dc=com" –desc "Marketing Director"
The –memberOf switch requires the full distinguished name (DN) of each group the user should be added to; if you want to add the user to multiple groups you can add multiple DNs separated by spaces.
If any element contains a space, such as the DN of the Help Desk group, it needs to be enclosed in double quotes. If an element contains a backslash, like an OU called IT\EMEA, the backslash must be entered twice: IT\\EMEA. (These requirements apply to all of the ds* tools.)
When you use the -pwd * switch, you’ll be prompted to enter a password for the user at the command line. You can specify the password within the command itself (-pwd P@ssword1), but this will display the password in plain text on the screen or in any text or script file that you’ve embedded the command into.
Similarly, you can create a group object and an OU using the following two commands:
dsadd computer cn=WKS1,ou=Workstations,dc=contoso,dc=com dsadd ou "ou=Training OU,dc=contoso,dc=com"
Dsmod is used to modify an existing object, and you work with it much as with dsadd, using different submenus and syntax depending on the type of object you’re modifying. The following dsmod statement changes a user’s password and modifies his account so he will be prompted to change to a new password on next logon:
dsmod user "cn=afuller,ou=IT,dc=contoso,dc=com" –pwd P@ssw0rd1 –mustchpwd yes
To see how similar these switches are, look at the dsadd syntax you would use to create this user with the same attributes configured:
dsadd user "cn=afuller,ou=IT,dc=contoso,dc=com" –pwd P@ssw0rd1 –mustchpwd yes
As you can clearly see, if you know the switches to create objects in dsadd, you can use those same switches to modify users with dsmod.
The converse of dsadd is dsrm; as you might imagine, this tool lets you delete an object from the command line. The basic dsrm syntax is pretty straightforward: simply enter dsrm followed by the distinguished name of the object you want to delete, like so:
By default, dsrm will prompt “Are you sure you want to delete this object?” Type Y, then press Enter. You can suppress this prompt using the –noprompt switch, but, obviously, you then get no chance to confirm that you’ve selected the correct object before deleting it. Two additional switches can be helpful if you are deleting a container object, that is, an organizational unit that could potentially contain other objects within it. The following command deletes the TrainingOU organizational unit and all objects contained within it:
dsrm ou=TrainingOU,dc=contoso,dc=com –subtree
This one deletes all child objects contained within TrainingOU but leaves the organizational unit object itself in place:
dsrm ou=TrainingOU,dc=contoso,dc=com –subtree –exclude
To move or rename an object in Active Directory, you use the dsmove tool, but note that you should use it to move an object only within a single domain. To migrate objects between domains or forests, use the Active Directory Migration Tool (ADMT), a free download from the Microsoft Web site. Dsmove relies on two switches that can be used separately or in combination. This command gives Steve Conn’s account a new last name:
dsmove "cn=Conn, Steve,ou=IT,dc=contoso,dc=com" –newname "Steve Conn"
This command moves Steve’s account from the IT OU to the Training OU:
dsmove "cn=Conn, Steve,ou=IT,dc=contoso,dc=com" –newparent ou=Training,dc=contoso,dc=com
You can combine a rename and a move into a single operation by specifying both switches at once, like this:
dsmove "cn=Conn, Steve,ou=IT,dc=contoso,dc=com" –newname "Steve Conn" –newparent ou=Training,dc=contoso,dc=com
Dsget and Dsquery
The ds* command-line toolset also includes two tools used to query Active Directory for information rather than for creating or modifying objects.
Dsget takes an object’s DN as input and provides you with the value of the attribute or attributes you specify. Dsget uses the same submenus as dsadd and dsmod—user, computer, contact, group, ou, and quota.
To obtain the SAM Account Name and Security Identifier (SID) of a user account, enter the following command (note that the following is all on one line):
dsget user cn=afuller,ou=IT,dc=contoso,dc=com –samAccountName –sid
You’ll get output such as that in Figure 3.
Figure 3 Running dsget (Click the image for a larger view)
Dsquery returns a list of Active Directory objects that meet criteria you specify. You can specify the following parameters no matter which submenu you’re using:
dsquery <ObjectType> <StartNode> -s <Search Scope> -o <OutputFormat>
For ObjectType, dsquery can use the following submenus, each of which has its own syntax: computer, contact, subnet, group, ou, site, server (note that the server submenu retrieves information about domain controllers, not any member servers in your environment), user, quota, and partition. And if one of these query types doesn’t fit the bill, you can use the * submenu, which lets you enter a free-form LDAP query.
StartNode specifies the location in the Active Directory tree where the search will start. You can use a specific DN such as ou=IT,dc=contoso,dc=com, or one of the following shortcut specifiers: domainroot, which begins at the root of a particular domain, or forestroot, which begins at the root of the forest root domain using a Global Catalog server to perform the search.
Finally, the Search Scope option specifies how dsquery should search the Active Directory tree. Subtree (the default) queries the specified StartNode and all of its child objects, onelevel queries only the immediate children of the StartNode, and base queries the StartNode object only.
To better understand search scopes, consider an OU that contains both user objects and a child OU that itself contains additional objects. Using the subtree scope will query the OU, all of the user objects contained within it, and the child OU and its contents. The onelevel scope will query only the users contained within the OU and will not query the child OU or its contents. A base query will search only the OU itself without querying any of the objects contained within it.
Finally, you can use Output Format to control how the results of dsquery are formatted. By default, dsquery returns the distinguished names of any objects that match the query, like this:
To query for all user objects contained within the IT OU and any child OUs, use the following:
dsquery user ou=IT,dc=contoso,dc=com
You can further refine this query by adding additional switches such as -disabled, which returns only disabled user accounts; -inactive x, which returns only users who haven’t logged on in the past x weeks or more; or -stalepwd x, which will return only users who have not changed their passwords in x days or more.
Depending on the number of objects in your directory, you may need to specify the -limit x switch when running your query. By default, dsquery will return up to 100 objects that match the specifics of your query; you can specify a larger number such as -limit 500, or use -limit 0 to instruct dsquery to return all matching objects.
You can use the other submenus to perform useful queries for other object types as well. Consider the following query, which returns every subnet defined in Active Directory Sites and Services that’s in the 10.1.x.x address space:
dsquery subnet –name 10.1.*
Or use the following to return every subnet located in the Corp site:
dsquery subnet –site Corp
With another submenu, you can quickly determine how many domain controllers in your forest are configured as Global Catalog servers:
dsquery server –forest –isgc
You can also use this syntax to help you determine which domain controller in your domain hosts the Primary Domain Controller (PDC) Emulator Flexible Single Master Operations (FSMO) role:
dsquery server –hasfsmo pdc
As with the other ds* commands that include submenus, you can view all of the switches available within a particular dsquery submenu by going to the command prompt and typing dsquery user /?, dsquery computer /?, dsquery subnet /?, and so forth.
An additional slick trick is to pipe the output of dsquery into another tool such as dsmod using the | character (shift-backslash on U.S. keyboards). For example, let’s say your company has renamed a department from Training to Internal Development and now you have to update the description field of each relevant user from the old department name to the new. On a single command line, you can query for user objects that have a description field of Training and then modify that description field in bulk, as follows:
dsquery user –description "Training" | dsmod -description "Internal Development"
Some Third-Party Gems
Because Active Directory is based on LDAP standards, you can query and modify it using any tool that can speak LDAP. Many third-party vendors have released fee-based tools to assist you in administering Active Directory, but sometimes you find a treasure that has been made available to the community at no charge. Such is the case with a collection created by Directory Services MVP Joe Richards, available for download from joeware.net/freetools. There you’ll find numerous tools to serve many different functions. Three that I turn to again and again are adfind, admod, and oldcmp.
Adfind and Admod
Adfind and admod are similar to dsquery and dsmod; adfind is a command-line query tool for Active Directory, and admod can create, delete, or modify one or more Active Directory objects.
Unlike the ds* tools that have multiple submenus and different switches depending on the type of object, adfind and admod have a consistent syntax regardless of the type of query or modification you’re trying to perform. The basic syntax for adfind is:
adfind –b <Search Base> -s <Search Scope> -f <Search Filter> attributesDesired
So a query for the DN and description of all computer objects within your domain would be:
adfind –b dc=contoso,dc=com –s subtree –f (objectclass=computer) dn description
A query for all user objects would look like this:
adfind –b dc=contoso,dc=com –s subtree –f "(&(objectcategory=person) (objectclass=user))" dn description
Notice that except for the contents of the LDAP query, the syntax has not changed.
As you work with adfind, you’ll find a number of shortcut operators that can save you a lot of typing. For example, the -default switch can replace -b dc=contoso,dc=com in the previous example and search your entire domain; -gc searches against a global catalog (GC) and returns all users in your Active Directory forest. You can also use the -rb switch to set a relative base for your search; if you want to search the Training OU in the phl.east.us.contoso.com domain, you can save yourself quite a bit of effort by simply specifying –default –rb ou=Training rather than –b ou=Training, dc=phl,dc=east,dc=us,dc=contoso,dc=com.
Adfind can also perform a number of advanced search functions that can’t be easily managed at the command line otherwise, including those shown in Figure 4.
Figure 4 Adfind switches
|Queries the Deleted Objects container for tombstone objects.
|Queries against bitwise operators such as the userAccountControl attribute.
|Performs an attribute-scoped query. This function (which can’t be replicated in dsquery) can retrieve an attribute of a particular object and then perform a query against it.
|Pipes the output of an adfind query into dsmod or one of the other ds* tools.
An example using the –asq switch would be “Show me the group memberships of the members of the HelpDesk,” like this:
adfind –default –rb cn=HelpDesk,ou=IT –asq member memberOf
Admod, as its name suggests, is used to modify objects within Active Directory. As with adfind, there are no specialized submenus with particular syntaxes to remember; admod uses the same syntax regardless of the type of object you’re working with. You can also use admod to add, move, rename, delete, and even undelete objects simply by adding the appropriate switch, such as -add, -rm, -move, -undel. And just as with dsquery and dsmod, you can also use the | character to pipe the results of an adfind query into admod.
Note that performing an undelete with admod simply performs a tombstone reanimation operation, in which most of the objects attributes have been removed. To fully restore an object and all of its attributes, you’ll still need to perform an authoritative restore of the object.
There’s one additional joeware tool I consider an indispensable part of my automation toolkit: oldcmp, which scans your Active Directory database for computer accounts that have not been used in a specified number of weeks and can do the following:
- Create a report of accounts without taking any action against them
- Disable the unused computer accounts
- Move the computer accounts to a different OU that you designate
- Delete the computer accounts outright
Note that because oldcmp has the potential to wreak serious havoc on your directory, it has a number of built-in safety features. It will not delete any account that has not already been disabled (and without manually specifying a “No really, I mean it!” command-line switch). It will not modify more than 10 objects at a time without a similar “No really, I mean it!” switch, and it absolutely will not do anything to the computer account for a domain controller.
Despite the now-misleading name of the tool, Joe has updated oldcmp so that it will perform similar functions for user accounts that have not been used for a certain amount of time as well.
For a small Active Directory environment or one where you’re only working with one or two additions or changes at a time, the GUI tools such as Active Directory Users and Computers might be sufficient for day-to-day administration. But if you’re adding and modifying large numbers of objects on a daily basis or simply want a more streamlined solution for your administrative tasks, moving to the command line can greatly speed up the process of creating, modifying, and deleting objects within Active Directory. As you’ve seen, there are a number of flexible and powerful tools available free of charge, both built right into Windows and downloadable from members of the Active Directory community. Any of these tools has the ability to greatly enhance your productivity as an Active Directory administrator, and together they become even more essential to your daily work life.