Home All Groups Group Topic Archive Search About

Active Directory VBScript to get user's OU information

Author
9 Jul 2009 8:34 PM
Daniel
I am trying to create a vbscript that go through the list of AD2003 users and
finds their primary SMTP email addresses and their department value in their
accounts.  The problem I'm facing is LDAP ADSI provider needs the exact OU
container of each account before it can list email address and department but
the users in this list are scattered across different OUs.  Does anybody know
a way to pull exact OU location of where a AD account is residing, for
example "cn=user,OU=Users,OU=xxx,DC=yyy,DC=local"? There is ADsPath attribute
in ADSI but this attribute needs the exact OU container first to find this
info. It would be greatly appreciated if anybody out there can point me in
the right direction.

Author
9 Jul 2009 9:39 PM
Richard Mueller [MVP]
Show quote Hide quote
"Daniel" <Dan***@discussions.microsoft.com> wrote in message
news:A026D739-5D33-489E-A666-AFC998075B36@microsoft.com...
>I am trying to create a vbscript that go through the list of AD2003 users
>and
> finds their primary SMTP email addresses and their department value in
> their
> accounts.  The problem I'm facing is LDAP ADSI provider needs the exact OU
> container of each account before it can list email address and department
> but
> the users in this list are scattered across different OUs.  Does anybody
> know
> a way to pull exact OU location of where a AD account is residing, for
> example "cn=user,OU=Users,OU=xxx,DC=yyy,DC=local"? There is ADsPath
> attribute
> in ADSI but this attribute needs the exact OU container first to find this
> info. It would be greatly appreciated if anybody out there can point me in
> the right direction.

If your list of users has Common Names, it cannot easily be done. Common
Names do not uniquely identify the users. More likely, you list is of
"pre-Windows 2000 logon" names, also called NT names (or sometimes UserID).
Technically, this is the value of the sAMAccountName attribute and uniquely
identifies the object in the domain. You can use the NameTranslate object to
convert the sAMAccountName (in conjunction with the NetBIOS name of the
domain) into the Distinguished Name. This works not matter which OU the
object resides in. See this link for details:

http://www.rlmueller.net/NameTranslateFAQ.htm

An example might be:
========
Const ForReading = 1
' Constants for the NameTranslate object.
Const ADS_NAME_INITTYPE_GC = 3
Const ADS_NAME_TYPE_NT4 = 3
Const ADS_NAME_TYPE_1779 = 1

' Determine DNS name of domain from RootDSE.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")

' Use the NameTranslate object to find the NetBIOS domain name from the
' DNS domain name.
Set objTrans = CreateObject("NameTranslate")
objTrans.Init ADS_NAME_INITTYPE_GC, ""
objTrans.Set ADS_NAME_TYPE_1779, strDNSDomain
strNetBIOSDomain = objTrans.Get(ADS_NAME_TYPE_NT4)
' Remove trailing backslash.
strNetBIOSDomain = Left(strNetBIOSDomain, Len(strNetBIOSDomain) - 1)

' Specify file of user names.
strFile = "c:\Scripts\Users.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile(strFile, ForReading)

Do Until objFile.AtEndOfStream
    strNTName = Trim(objFile.ReadLine)
    ' Skip blank lines.
    If (strNTName <> "") Then
        ' Use the Set method to specify the NT format of the object name.
        ' Trap error if user does not exist.
        On Error Resume Next
        objTrans.Set ADS_NAME_TYPE_NT4, strNTName
        If (Err.Number = 0) Then
            On Error GoTo 0
            ' Use the Get method to retrieve the RPC 1779 Distinguished
Name.
            strUserDN = objTrans.Get(ADS_NAME_TYPE_1779)

            ' Bind to the user object (if desired).
            Set objUser = GetObject("LDAP://" & strUserDN)
            ' Do whatever you want...
        Else
            On Error GoTo 0
            ' Alert user about bad user name.
            Wscript.Echo "User " & strNTName & " does not exist"
        End If
    End If
Loop

objFile.Close
========
Some code is required, but the NameTranslate interface is very efficient.

If your file has user Common Names, you can use ADO to query AD for the user
object with that value assigned to the cn attribute. If there is no result,
echo an error message. If there is one result, retrieve distinguishedName
and proceed. And, if there is more than one result echo a message
explaining. Reply if you need this. Obviously, the repeated searches of AD
would be slower, but can be done.

--
Richard Mueller
MVP Directory Services
Hilltop Lab - http://www.rlmueller.net
--
Author
10 Jul 2009 5:49 AM
Mark D. MacLachlan
Give this a try, it shoudl enumerate all users in the domain and
produce a report for you.  The report is tab separated, so you can open
it in Excel.

[code]
Dim qQuery, objConnection, objCommand, objRecordSet, obj
Dim oRootDSE, strDomain

Set oRootDSE = GetObject("LDAP://rootDSE")
strDomain = oRootDSE.get("defaultNamingContext")

' other categories = computer, user, printqueue, group
qQuery = "<LDAP://" & strDomain &">;" & _
        "(objectCategory=person)" & _
       ";name,proxyAddresses,department;subtree"

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Open "Provider=ADsDSOObject;"
objCommand.ActiveConnection = objConnection
objCommand.CommandText = qQuery
Set objRecordSet = objCommand.Execute

While Not objRecordSet.EOF
    Report = Report & objRecordSet.Fields("name")
    For Each address In proxyAddresses
        If Left(address,4) = "SMTP" Then
            Report = Report & vbTab & address & vbTab
        End If
    Next
    Report = Report & objRecordSet.Fields("department") & vbCrLf
    objrecordset.MoveNext
Wend

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set ts = objFSO.CreateTextFile("SMTPDepartmentReport.txt",True)
ts.Write Report
ts.Close
objConnection.Close
[/code]

Hope that helps,

Mark D. MacLachlan