There are several ways of treating directory objects of the same type (enumerating objects). Generally, the most preferable way is the following one:
Use ActiveX Data Objects (ADO) for searching Active Directory, and obtain a set of necessary objects. (Remember that access through ADO is read-only!)
Bind directly to an object found.
Carry out modifications.
Repeat Steps 2 and 3 for the next object found.
Nevertheless, it is also possible to filter out, or enumerate child objects located in containers. This approach spreads over one selected domain only. Let us discuss some facts that you must take into consideration.
It is clear that the members of a group are not child objects of that group, so you cannot use filtering. There is a special way to enumerate group members (see the "Manipulating Group Memberships" sections).
The flat WinNT namespace can have advantages if you need to find similar objects in an entire domain. However, you will not be able to determine locations of found objects in the OU structure.
If the filter is not set, is set to empty, or is not correct, all objects of all classes will be retrieved. In the case of the LDAP provider, an incorrect filter will produce an empty result.
The following program (Listing 17.6) finds all groups in a domain.
Listing 17.6. Filtering.bas — Using Filters with Different Providers
Option Explicit Sub Main() Dim objAD As IADsContainer Dim obj As IADs Dim i As Integer Set objAD = GetObject ("WinNT: //NET,domain") ' Or, you can bind to a computer object: ' Set objAD = GetObject ("WinNT : //netdc1, computer") ' Using the LDAP provider is not effective, since you cannot filter ' objects in the nested containers. WinNT namespace is flat, ' so all objects are "visible" at the same level. ' The following string will allow you to find objects ' at one level only: ' Set objAD = GetObject ("LDAP: //DC=net, DC=dom") objAD.Filter = Array ("group") ' "user" and "computer" are also acceptable for domain objects. ' You can specify two or more object types in the same filter: ' objAD.Filter = Array ("group", "user") ' "printQueue" and "service" can be specified for computer objects ' and the WinNT provider. ' With the LDAP provider, you can also select the following object ' classes: ' printQueue, builtinDomain, container, organizationalUnit, volume. i = 1 For Each obj In objAD Debug.Print i; obj.Name; " ("; obj.ADsPath; ") " i = i + 1 Next Set objAD = Nothing Set obj = Nothing End Sub
The following program (Listing 17.7) enumerates all children of both the domain object and nested containers. Thus, all objects of a specified type can be found, and the directory path to each object reflects its location in the entire domain namespace (taking into account the OU structure). This script, however, runs slower than the previous one.
Listing 17.7. EnumeratingInLDAP.bas — Using Recursion and the LDAP Provider
Option Explicit Sub Main() Dim objAD As IADsContainer Dim strClass As String Dim i As Integer i = 1 strClass = "group" 'or obj.Class = "user", etc. Set objAD = GetObject ("LDAP: //DC=net, DC=dom") Call getGroups (objAD, strClass, i) End Sub Sub getGroups (objRoot, strType, i) Dim obj As IADs For Each obj In objRoot If obj.Class = strType Then Debug.Print i; obj.Name + " . . . . . " + obj.ADsPath i = i + 1 End If If obj.Class = "organizationalUnit" _ Or obj.Class = "builtinDomain" _ Or obj.Class = "container" Then Call getGroups (obj, strType, i) End If Next End Sub