How Can I List All the Sub-OUs in an OU?
Hey, Scripting Guy! How can I list all the sub-OUs in an OU? That includes any OUs that might be in those sub-OUs.
Hey, JE. If you’re the least bit familiar with this column then you know that we Scripting Guys love to answer questions that involve searching Active Directory. That’s because we never bother to write detailed explanations of how the scripts we show you work; instead, we just refer you to our two-part Tales from the Script series Dude, Where’s My Printer? If you’ve been playing along at home and if you picked January 13th as the first day in the year 2006 that the Scripting Guys would tackle a question involving Active Directory search, well, congratulations: you’re a winner.
Note. So is it really true that explaining how an Active Directory search script works would exceed the scope of this column? Man, who told you that? Oh, right: we did. Um, yes, yes, explaining how an Active Directory search script works does exceed the scope of this column; it has nothing to do with the Scripting Guys being lazy. No, nothing at all …. (Editor’s Note: Editing for accuracy: It has everything to do with the Scripting Guys being lazy.)
Now, to be fair, we don’t have to use an Active Directory search to retrieve a list of all the sub-OUs (and sub-sub-OUs, etc.) within a specific OU; we could achieve the same results using a recursive function. In general, though, recursive functions are not only difficult to write but also difficult to visualize and understand. We’re simple guys, and we find Active Directory search scripts much simpler to deal with. Consequently, that’s the route we took:
On Error Resume Next
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://ou=finance,dc=fabrikam,dc=com’ WHERE ” & _ “objectCategory=’organizationalUnit'” Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst Do Until objRecordSet.EOF Wscript.Echo objRecordSet.Fields(“ADsPath”).Value objRecordSet.MoveNext Loop
This might look a bit intimidating to newcomers, but most of this script is boilerplate; it’s the same code you’ll find in almost every Active Directory search script. Because of that we’re going to focus on just one small piece of the puzzle, the SQL statement we use to query Active Directory. If you have no idea what an ADODB.Connection object is used for then we recommend you take a look at our two-part Tales from the Script series Dude, Where’s My Printer?
Oh, right: we did mention that already, didn’t we?
Here’s the code of interest:
objCommand.CommandText = _ “SELECT ADsPath FROM ‘LDAP://ou=finance,dc=fabrikam,dc=com’ WHERE ” & _ “objectCategory=’organizationalUnit'”
What we’re doing here is selecting the ADsPath attribute for all organizational units found in the Finance OU in fabrikam.com. How do we know that we’re getting back the organizational units found in the Finance OU in fabrikam.com (and only those organizational units)? Two reasons: First, we know we’re going to get back only OUs because our Where clause limits us to items that have an objectCategory equal to organizationalUnit. That’s going to filter out user accounts, groups, print queues, and anything else that might be found in Active Directory.
That makes sense. But how do we know we’ll get back only those OUs that can be found in the Finance OU? Because, in this script, we don’t start our search in the Active Directory root; instead we start it in the Finance OU itself: LDAP://ou=finance, dc=fabrikam, dc=com. That means we’re going to search only the Finance OU and any other containers found in that OU; we aren’t even going to take a peek anywhere else. In turn, that means anything we get back from this script has to be within the Finance OU. Suppose we wanted to find all the OUs located in the West Coast OU, which happens to be in the USA OU? Then we’d target our query like so:
objCommand.CommandText = _ “SELECT AdsPath FROM ‘LDAP://ou=West Coast,ou=USA,dc=fabrikam,dc=com’ WHERE ” & _ “objectCategory=’organizationalUnit'”
So when will the Scripting Guys tackle another Active Directory search question? Well, we thought about starting an office pool and taking bets on the next date, but then someone pointed out that we could cheat and just wait until the date we picked before answering another Active Directory search question. The Scripting Guys cheat? Say it isn’t so! ((Although, knowing the Scripting Guys, we’d probably lose the office pool even if we did cheat. Which helps explain why we all live in Redmond, WA rather than, say, Monte Carlo.)