How Can I Display a Multi-Valued Attribute Returned from an Active Directory Search?
Hey, Scripting Guy! How can I display a multi-valued attribute that I get back when using ADO to search Active Directory?
Hey, ES. For the most part Active Directory is a script writer’s paradise; with very few exceptions anything you can do using the Active Directory snap-ins and GUI tools you can also do using a script. Of course, that doesn’t mean there aren’t a few bumps in the road. For example, dealing with dates and times in Active Directory can be a bit… challenging. After all, not only does Active Directory use some crazy date-time formats, but it also uses different date-time formats for different attributes. How…nice….
Another challenge crops up with multi-valued attributes. Most Active Directory properties are single-valued; in other words, the attribute can hold only one value. Names, for example, are single-valued: a user can have only one distinguished name, one SAM Account name, one first name, one last name, etc. Likewise, an account can have only one creation date and one last modified date; an account can be disabled or enabled but it can’t be both. Single-valued attributes? Piece of cake.
Multi-valued attributes are a different story. As the name implies, multi-valued attributes can contain more than one value. Take phone numbers, for example. As scary as this might be, it’s not unusual for people to have more than one home phone number or more than one cell phone number. The designers of Active Directory could have chosen to ignore that reality and limit people to a single home phone number; alternatively, they could have created scores of additional attributes: homePhone1, homePhone2, homePhone3, homePhone4, etc. Neither of those approaches was particularly appealing. Therefore the decision was to create multi-valued attributes: a single property that could contain a whole bunch of values. There’s a single-valued attribute that represents your primary home phone number, but there’s also a multi-valued attribute that can hold as many additional home phone numbers as you might have (555-1111; 555-2222; 555-3333; etc.).
That’s actually a pretty good solution; the only problem is that you can’t directly echo the value of a multi-valued attribute. Suppose you’ve just conducted a search of Active Directory and returned the otherHomePhone attribute. If you try echoing the value using this line of code you’re going to get a “Type mismatch” error:
The problem is that a multi-valued attribute is actually an array of values; you can’t echo the value because arrays don’t have a single value. Instead, you need to create a For Each loop and echo each of the values found in the array of values:
For Each strPhone in objRecordSet.Fields(“otherHomePhone”).Value Wscript.Echo strPhone Next
That’s the secret right there: create a For Each loop and display each value in the array of values. This will work whether the user happens to have one additional home phone number, no additional home phone numbers, or scores of additional home phone numbers.
See, not too bad. Here’s a sample script that uses ADO to search Active Directory and echo back the Name and the otherHomePhone attribute values for each user in the domain. As you might have guessed, otherHomePhone happens to be a multi-valued attribute. But that’s all right; we just use a For Each loop to loop through all the other home phone numbers for each user.
Here’s the script:
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 Name,otherHomePhone FROM ‘LDAP://dc=fabrikam,dc=com’ WHERE objectCategory=’user'” Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst Do Until objRecordSet.EOF Wscript.Echo objRecordSet.Fields(“Name”).Value If Not IsNull(objRecordSet.Fields(“otherHomePhone”).Value) Then For Each strPhone in objRecordSet.Fields(“otherHomePhone”).Value Wscript.Echo “Home phone: ” & strPhone Next End If objRecordSet.MoveNext Loop
We did do one additional thing here: we checked to see if the otherHomePhone attribute was null (that is, we checked to see if the user actually had another home phone number). That’s what we do with this line of code:
If Not IsNull(objRecordSet.Fields(“otherHomePhone”).Value) Then
Why did we do that? Well, suppose the user didn’t have another home phone number. In that case our script would echo a line like this:
In our case we didn’t want to clutter the output with lines like this. However, if you’d prefer to see that a user doesn’t have any additional home phone numbers then simply remove the If-Then statement. In other words:
Do Until objRecordSet.EOF Wscript.Echo objRecordSet.Fields(“Name”).Value For Each strPhone in objRecordSet.Fields(“otherHomePhone”).Value Wscript.Echo “Home phone: ” & strPhone Next objRecordSet.MoveNext Loop
Incidentally, if you’d like to know more about searching Active Directory (something we just plain ignored in today’s column) check out this month’s Tales from the Script.