Hey, Scripting Guy! Given a distinguished name, how can I determine the “topmost” OU?

-- HF

Hey, HF. You know, as he was driving in to work this morning, the Scripting Guy who writes this column heard an advertisement for a series of adult education courses being offered by a local community college. As you might expect, this commercial pointed out that taking these courses will make you smarter and help you get a better job; what was interesting, though, is that the ad also implied – slyly – that taking these courses will make it easier for to pick up girls (or guys). In other words, not only will education make you smarter, but it will make you more attractive as well.

Oddly enough, that caused the Scripting Guy who writes this column to reflect back on his college days. One of the first college classes this Scripting Guy ever took was Astronomy 101. (It was also one of the best classes he ever took, and to this day he still wonders why he didn’t take any more astronomy classes, or maybe even become an astronomer.) During one class the instructor noted that “The obliquity of the ecliptic is 23½ degrees.” He paused for a moment and then added, “If you remember nothing else from this course remember that. People will think you’re pretty sexy if you know that the obliquity of the ecliptic is 23½ degrees.”

As it turns out, the Scripting Guy who writes this column did remember that the obliquity of the ecliptic is 23½ degrees. (Actually it’s a tiny bit less than that, but that’s close enough, especially for a column that’s supposed to be about system administration scripting.) So did it work, do people think that the Scripting Guy who writes this column is pretty sexy? Let’s put it this way: not everything you learn in college turns out to be true.

Not by a long shot.

In other words, we can’t promise you that a little knowledge will make you more attractive. However, it will help you determine the topmost OU for an Active Directory object:

```Set objSysInfo = CreateObject("ADSystemInfo")

arrDN = Split(strDN, ",")

For i = UBound(arrDN) to 0 Step -1
If Left(arrDN(i), 3) = "OU=" Then
arrOU = Split(arrDN(i), "=")
Wscript.Echo arrOU(1)
Exit For
End If
Next
```

Before we begin explaining the script let’s take a minute to explain the scenario. We have the distinguished name for an object (say, a user account). That’s going to look something like this:

```cn=Ken Myer,OU=Level4,OU=Level3,OU=Level2,OU=Level1,DC=fabrikam,DC=com
```

As you can see, the Ken Myer account resides in the Level4 OU. Level4, in turn, is a child OU of Level3, which is a child OU of Level2, which is a child OU of Level1. (In a distinguished name the item to the right is always a parent of the item to the left.) Level1 also happens to be the “topmost” OU; it’s not a child of any other OU. This is the OU that we need to identify.

Now, in a previous column we showed you how to identify the “grandparent” OU for a given container. We can’t use that approach here simply because we aren’t sure how many levels we need to go up in order to find the topmost OU. Well, OK, if you want to get technical we could use that approach, albeit with a few modifications; however, we think we came up with a solution that’s a little bit easier to implement.

Of course, none of these approaches are of much use unless we have a distinguishedName attribute to work with. To take care of that problem, and for illustration purposes, we’ve used this block of code to grab the distinguished name of the logged-on user:

```Set objSysInfo = CreateObject("ADSystemInfo")
```

All we’re doing here is creating an instance of the ADSystemInfo object, an object that retrieves information about the logged-on user and his or her computer. (And before you ask, sorry: the ADSystemInfo object can only be used locally. That means this script can’t be readily-modified to retrieve information about the user logged on to a remote computer. But don’t despair; in an upcoming edition of TechNet Magazine we’ll discuss that very issue.) After creating the ADSystemInfo object we then assign the value of the UserName property to the variable strDN. And guess what? The value of the UserName property just happens to be the distinguished name of the logged-on user:

```cn=Ken Myer,OU=Level4,OU=Level3,OU=Level2,OU=Level1,DC=fabrikam,DC=com
```

That’s nice, isn’t it? Except for one thing: how the heck do we determine the topmost OU given a value like that?

There are, admittedly, different ways of doing this. For various reasons (simplicity being the primary reason) we decided to start out by using the Split function to turn this distinguished name into an array named arrDN:

```arrDN = Split(strDN, ",")
```

By splitting the string on the comma we end up with an array consisting of the following items:

```cn=Ken Myer
OU=Level4
OU=Level3
OU=Level2
OU=Level1
DC=fabrikam
DC=com
```

As you probably know, in a distinguished name the topmost OU will always be the OU nearest the domain components (the DC= things). In this case, it’s the Level1 OU that’s nearest the domain components: cn=Ken Myer,OU=Level4,OU=Level3,OU=Level2,OU=Level1,DC=fabrikam,DC=com. So is there an easy way to determine which OU is nearest the domain components? You bet there is:

```For i = UBound(arrDN) to 0 Step -1
```

What we’ve done here is set up a For Next loop to loop through all the items in the array arrDN. But this isn’t your ordinary For Next loop, one that starts with the first item in the array and works its way towards the last item. Instead, we’re starting with the last item in the array (something we can determine using the UBound function) and working our way backwards towards the first item. In our example, we have an array with 7 items; that means that the last item in the array has an index number of 6. (Because the first item in an array is 0 the last item will always be the total number of items minus 1.) That means we’re going to start out with the item that has the index number 6. What do we do when we’re done with that item? That’s easy: we’ll then look at item 5; that’s what the Step -1 parameter is for. We’ll continue doing this until we’ve disposed of item 0; at that point our loop will be complete, and we’ll have looked at each and every item in the array.

 Note. OK, to be completely accurate, we probably won’t look at all the items in the array. But we’ll explain that in just a second.

Inside the loop we start out by checking to see if the first three characters in the item happen to be OU=. That’s what we use this line of code, and the Left function, for:

```If Left(arrDN(i), 3) = "OU=" Then
```

In our example item 6 (the first item we look at) is this: DC=com. Are the first three letters in DC=com equal to our target value (OU=)? No, they aren’t. Therefore, we loop around and check the next item in the array, DC=fabrikam. Do we have a match? Nope. And so we loop around and check the next item: OU=Level1. What do you know: we’ve got ourselves a winner!

Having found the topmost OU we’re now practically done; in fact, if we wanted to, we could simply echo back the value OU=Level1 and call it good. However, we decided to get rid of the OU=, just to make things a little neater and cleaner. That’s what we do here:

```arrOU = Split(arrDN(i), "=")
Wscript.Echo arrOU(1)
```

In the first line above we use the Split function to create another array named arrOU. This time we split the value on the equals sign (=), yielding an array with these two items:

```OU=
Level1
```

And then in line 2 we echo back the value of the second item in the array:

```Level1
```

At that point we truly are finished. Consequently, we call the Exit For statement to exit our For Next loop and then call it good. That should be all you need, HF, at least when it comes to determining the topmost OU of an Active Directory object.

Incidentally, the Scripting Guy who writes this column was a little disappointed to discover that learning that the obliquity of the ecliptic was 23½ degrees didn’t make him more attractive and desirable. On the other hand, back when the Scripting Guy who writes this column first started college people still believed that the Sun revolved around the Earth. All things considered, he was just happy that no one tried burning him at the stake for claiming that the obliquity of the ecliptic was 23½ degrees.

 Note. What if someday he changes his mind and wants to be burned at the stake? No problem; there are plenty of people here at Microsoft who would be more than happy to help him out with that.