Platform SDK: Active Directory, ADSI, and Directory Services

LDAP Dialect

An LDAP dialect string consists of four parts separated by semicolons (;).

The following is an example of the LDAP dialect in ADSI that searches all the objects in the subtree.

"<LDAP://DC=Microsoft,DC=com>;(objectClass=*);AdsPath, cn; subTree"

Not all search options (for example, search scope, search page size) can be expressed in the SQL dialect, so you need to set the options before the actual query execution starts.

You can also add wildcards and conditions to an LDAP string. The following examples show substrings that can be used to search the directory.

Get all entries:

(objectClass=*)

Get entries containing 'bob' somewhere in the common name:

(cn=*bob*)

Get entries with a common name greater than or equal to 'bob':

(cn>='bob')

Get all users with an email attribute:

(&(objectClass=user)(email=*))

Get all user entries with an email attribute and a surname equal to 'smith':

(&(sn=smith)(objectClass=user)(email=*))

Get all user entries with a common name that starts with 'andy', 'steve', or 'margaret':

(&(objectClass=user) | (cn=andy*)(cn=steve)(cn=margaret))

Get all entries without an email attribute:

(!(email=*))

The formal definition of the search filter is as follows (from RFC 1960):

<filter> ::= '(' <filtercomp> ')'
<filtercomp> ::= <and> | <or> | <not> | <item>
<and> ::= '&' <filterlist>
<or> ::= '|' <filterlist>
<not> ::= '!' <filter>
<filterlist> ::= <filter> | <filter> <filterlist>
<item> ::= <simple> | <present> | <substring>
<simple> ::= <attr> <filtertype> <value> 
<filtertype> ::= <equal> | <approx> | <ge> | <le>
<equal> ::= '='
<approx> ::= '~='
<ge> ::= '>='
<le> ::= '<='
<present> ::= <attr> '=*'
<substring> ::= <attr> '=' <initial> <any> <final>
<initial> ::= NULL | <value>
<any> ::= '*' <starval>
<starval> ::= NULL | <value> '*' <starval>
<final> ::= NULL | <value>

The token <attr> is a string representing an AttributeType. The token <value> is a string representing an AttributeValue whose format is defined by the underlying directory service.

If a <value> must contain one of the characters * or ( or ), the character should be preceded by the slash \ escape character.

Example Code for Performing an LDAP Query

Dim con As New Connection, rs As New Recordset
Dim v
Dim Com As New Command
 
On Error GoTo bailout
 
'Open a Connection object.
con.Provider = "ADsDSOObject"
Debug.Print con.Properties.Count
For j = 0 To con.Properties.Count - 1
    Debug.Print con.Properties(j).Name
Next j
 
con.Open "Active Directory Provider", "CN=administrator,CN=users,DC=MyDomain,DC=Microsoft,DC=com", ""
 
'Create a command object on this connection.
Set Com.ActiveConnection = con
 
'Set the query string.
Com.CommandText = "<LDAP://MyServer/DC=MyDomain,DC=Microsoft,DC=com>;(objectClass=*);ADsPath, objectclass;base"
 
For j = 0 To Com.Properties.Count - 1
    Debug.Print Com.Properties(j).Name
Next j
 
'Set the preferences for Search.
Com.Properties("Page Size") = 1000
Com.Properties("Timeout") = 30 'seconds
 
'Execute the query.
Set rs = Com.Execute
 
For i = 0 To rs.Fields.Count - 1
    Debug.Print rs.Fields(i).Name, rs.Fields(i).Type
Next i
 
rs.MoveLast
Debug.Print "No. of rows = ", rs.RecordCount
 
'Navigate the record set.
rs.MoveFirst
While Not rs.EOF
    For i = 0 To rs.Fields.Count - 1
        If rs.Fields(i).Type = adVariant And Not (IsNull(rs.Fields(i).Value)) Then
            Debug.Print rs.Fields(i).Name, " = "
            For j = LBound(rs.Fields(i).Value) To UBound(rs.Fields(i).Value)
                Debug.Print rs.Fields(i).Value(j), " # "
            Next j
        Else
            Debug.Print rs.Fields(i).Name, " = ", rs.Fields(i).Value
        End If
    Next i
    rs.MoveNext
Wend
 
rs.MoveLast
Debug.Print "No. of rows = ", rs.RecordCount
 
Exit Sub
 
bailout:     Debug.Print "Error", Hex(Err.Number), " :", Error(Err.Number)
         Exit Sub