June 27th, 2005

How Can I Retrieve a List of OUs that have a Specific Word in Their Name?

Hey, Scripting Guy! Question

Hey, Scripting Guy! We have a number of OUs in our domain that have the word Servers in the OU name. How can I retrieve a list of those OUs?

— AM

SpacerHey, Scripting Guy! AnswerScript Center

Hey, AM. One of the Scripting Guys has a 15-year-old son who, whenever he hears his father tell a story about the good old days, rolls his eyes and says, “You’re just one of those old guys still living in the past.” (Of course, in the same breath this Scripting Son will say, “Remember when I was 10 and hit that home run against the Rockies?” but somehow that’s different.)

We mention this because your question takes us back to the good days, back to the glory years of the Hey, Scripting Guy! column. Back then it seemed like every other question we took had the same answer: you can find what you’re looking for by searching Active Directory. Did we do that because searching Active Directory is an incredibly powerful tool for system administrators, or did we do that because we were lazy and just liked giving the same answer over and over again? Well, we are lazy, but the truth is, ADO searches of Active Directory are enormously useful to system administrators. If you need a list of user accounts or a list of groups or a list of computers or a list of phone numbers or a list of just about anything, there’s a good chance you’ll find that information stored in Active Directory.

So, roll your eyes and sigh if you must, but here’s the answer to your question: you can find what you’re looking for by searching Active Directory. In fact, you can retrieve a list of OUs that have the word “Servers” in their name by using a script similar to this:

Const ADS_SCOPE_SUBTREE = 2

Set objConnection = CreateObject(“ADODB.Connection”) Set objCommand = CreateObject(“ADODB.Command”) objConnection.Provider = “ADsDSOObject” objConnection.Open “Active Directory Provider” Set objCommand.ActiveConnection = objConnection

objCommand.Properties(“Page Size”) = 1000 objCommand.Properties(“Searchscope”) = ADS_SCOPE_SUBTREE

objCommand.CommandText = _ “SELECT ADsPath FROM ‘LDAP://dc=fabrikam,dc=com’ ” & _ “WHERE objectCategory=’organizationalUnit’ AND Name = ‘*Servers*'”

Set objRecordSet = objCommand.Execute

objRecordSet.MoveFirst Do Until objRecordSet.EOF Wscript.Echo objRecordSet.Fields(“ADsPath”).Value objRecordSet.MoveNext Loop

We won’t go over this script in detail today; if you don’t have much experience with searching Active Directory you might take a look at our two-part series Dude, Where’s My Printer?, a series that explains the ADODB.Connection object and the Searchscope and all the other crazy-looking code found in this script. Instead we’ll just focus on the SQL query that actually returns the list of OUs for us:

objCommand.CommandText = _
    “SELECT ADsPath FROM ‘LDAP://dc=fabrikam,dc=com’ ” & _
        “WHERE objectCategory=’organizationalUnit’ AND Name = ‘*Servers*'”

What we’re doing here is searching the fabrikam.com domain and retrieving the ADsPath attribute. (Obviously we could have picked any other attribute, or even multiple attributes. We chose ADsPath because once you know the ADsPath for an object you can easily bind to that object and retrieve values for all its attributes.) That part’s pretty straightforward; what we’re really interested in is the WHERE clause:

WHERE objectCategory=’organizationalUnit’ AND Name = ‘*Servers*’

We use the WHERE clause to specify the criteria for our search, and in this case we’re looking for two things:

An objectCategory equal to organizationalUnit. As you might have guessed, an object with an objectCategory equal to organizationalUnit will be an OU. This part of our query weeds out users, computers, groups, sites, subnets, and any other kind of object stored in Active Directory.

OUs that have the word Servers somewhere in their Name attribute. Note the use of the wildcard character (the asterisk). This syntax *Servers* basically says, “We’re looking for the word Servers anywhere in the Name attribute. We don’t care what, if anything, comes before the word Servers (the first asterisk), and we don’t care what, if anything, comes after the word Servers (the second asterisk). We want any OU that has the word Servers somewhere in its Name.”

We could, of course, modify this syntax. What if we wanted to search only for Names that started with Servers (Servers-1, Servers-2, etc.)? Then we could search for this: Servers*. As you can see, in this case our Name has to start with the word Servers; we don’t care what comes after that. If we wanted to search for Names that ended with the word Servers (Asian Servers, North America Servers, etc.) we’d use this syntax: *Servers. It’s really no different than using wildcard characters to search for files or folders, something you’ve probably done a million times.

After defining the query we call the Execute method; this actually runs the query and returns a recordset containing all the OUs that have the word Servers somewhere in the Name. We then loop through the recordset and echo the ADsPath for each of these OUs. That’s all there is to it.

Incidentally, it’s usually not recommended that you search for text in the middle of a string (*Servers*); that’s because a search like that can be resource-intensive and take awhile for the domain controller to process. We can get away with it here because we’re assuming you don’t have millions of OUs to check; typically domains have far fewer OUs than they do, say, users or groups. Therefore we don’t expect this search to cause any problems.

Does that answer your question? Good. And, although you didn’t ask, we’re sure you’d like to hear about the time we almost-single-handedly beat Hanford High School, at that time undefeated and the number 1 ranked baseball team in the state of – oh, OK. But if the Scripting Son wants to talk about his home run from this season, you better not listen to him, either. (Although that was a nice hit. It reminded Scripting Dad of that one day in Richland when he….)

Author

0 comments

Discussion are closed.