How Can I Determine the OU a User Account Belongs To?

Hey, Scripting Guy! Question

Hey, Scripting Guy! How do I determine the OU a user account belongs to?

— CO

SpacerHey, Scripting Guy! AnswerScript Center

Hey, CO. Ah, yes: the OU a user belongs to. No doubt a lot of you are thinking, “Well, there’s probably an OU property of some kind in Active Directory that gives you that information. All you have to do is locate the user account, and then get the value of the OU property.”


That makes so much sense that – as you might have guessed – it’s not the way things work. As it turns out, there is no OU property (or anything equivalent) in Active Directory. But don’t fret. That doesn’t mean we can’t determine the user’s OU; it just means we – gasp! – have to work a little harder to do so.


For the purposes of this column, we’re assuming that you don’t know the user’s distinguished name; after all, with a distinguished name like CN=kenmyer,OU=Finance,DC-fabrikam,DC=com, well, even a Scripting Guy can figure out which OU the user belongs to. So we’ll assume that all you know is the user’s SAM account name, the name he or she typically uses to log on to the domain.


If you do know the SAM account name you’re in luck; that’s because these names must be unique in the Active Directory forest. Therefore, we can find this user by doing an Active Directory search:

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 distinguishedName FROM ‘LDAP://dc=fabrikam,dc=com’ WHERE objectCategory=’user’ ” & _
“AND sAMAccountName=’kenmyer'”
Set objRecordSet = objCommand.Execute

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


As we’ve noted before, there’s quite a bit involved in carrying out an Active Directory search, even though the script isn’t really all that long or all that complicated. For more information, check out this Scripting Guys’ Webcast.


Without going into any detail, what we’ve done here is search fabrikam.com for the user with the sAMAccountName kenmyer, As soon as we find him we echo his distinguished name (the distinguishedName attribute). Because that’s in the form CN=kenmyer,OU=Finance,DC=fabrikam,DC=com, we can look at the results and determine the user’s OU.


But the truth is, we’re too lazy to look at the user’s distinguished name; we want the script to do that for us. So let’s make a slight modification to our Do loop. Here’s the modified code; we’ll explain how it works in a second.

Do Until objRecordSet.EOF
strDN = objRecordSet.Fields(“distinguishedName”).Value
arrPath = Split(strDN, “,”)
intLength = Len(arrPath(1))
intNameLength = intLength – 3
Wscript.Echo Right(arrPath(1), intNameLength)
objRecordSet.MoveNext
Loop

Whoa! But don’t panic; this actually makes sense. We start, again, by getting the value of the user’s distinguished name; as we already know, this will be something like CN=kenmyer,OU=Finance,DC=fabrikam,DC=com.


We store this value in the variable strPath, then use the VBScript Split command to, well, split strPath into elements of an array. When we use the Split command and split on the comma (that is, we indicate that the comma is our delimiter, the character that separate the individual items in the string), we end up with an array that consists of the following elements:

CN=kenmyer
OU=Finance
DC=fabrikam
DC=com

We know that the second element in the array (and the second element in an array always has an index number of 1) is the OU where the user account resides. That means that, to get the name of the OU, we just need to take the second element (arrPath(1))and then get rid of the OU=.


Can we do that? Of course we can. We use the Len function to determine the number of characters in element 0 of our array. Remember, the value is OU=Finance, so the number of characters is 10.


Next we subtract 3 from the number of characters. Why? Well, we want to get rid of OU=, and OU= has three characters. Subtracting 3 from 10 leaves us with 7, which means we now know that the actual name of the OU – Finance – is 7 characters long.


Now – finally – we use the Right function to grab the last 7 characters in the string; in other words, we start at the e in OU=Finance and move back 7 characters. And guess what? You got it: the last 7 characters in OU=Finance just happen to be Finance, the name of the OU where the user account lives. Hey, we did it!


Here’s the revised script that searches Active Directory and reports back the OU where the user account resides.

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 distinguishedName FROM ‘LDAP://dc=fabrikam,dc=com’ “ & _
“WHERE objectCategory=’user’ ” & _
“AND sAMAccountName=’kenmyer'”
Set objRecordSet = objCommand.Execute

objRecordSet.MoveFirst
Do Until objRecordSet.EOF
strDN = objRecordSet.Fields(“distinguishedName”).Value
arrPath = Split(strDN, “,”)
intLength = Len(arrPath(1))
intNameLength = intLength – 3
Wscript.Echo Right(arrPath(1), intNameLength)
objRecordSet.MoveNext
Loop