Do you have a scripting-related question or problem? You can send your question or problem to [email protected]
For monitoring and reporting purposes, I need to know how many leaf (aka child) objects are in several of our Active Directory (AD) containers. I tried using the Active Directory Service Interfaces (ADSI) Count property in the script that Listing 1 shows, but this script fails with the error message C:\Scripts\Listing1.vbs(2, 1) Active Directory: Not implemented. How can I determine the number of objects in our AD containers?
As the error message suggests, the reason your script is failing is because the Count property isn't implemented by ADSI's LDAP provider, which means you can't use the property to determine the number of leaf objects in an AD container. You can work around the problem several ways. However, each solution has its drawbacks. The workarounds to count objects in an AD container include
- using a For Each...Next statement combined with a counter variable to enumerate and count the objects in the container
- using ADSI's ADsDSOObject provider (i.e., the OLE DB provider) to perform an ADO search, then using the ADO Command object's RecordSet.RecordCount property to read the number of records that the search returned
- using the new Windows Server 2003 attribute named msDS-Approx-Immed-Subordinates
Listing 2 demonstrates how to use the For Each...Next loop, which is also known as an enumerator, to count leaf objects. The script begins by initializing the counter variable named intContainerCount to 0. The script then binds to the target container and enumerates the objects in that container. During each iteration of the For Each...Next loop, intContainerCount increases by 1. After the loop finishes, the script echoes the total.
Although Listing 2 gets the job done, the script isn't particularly directory or network friendly when you run it remotely. Furthermore, it can be painfully slow when enumerating containers that contain hundreds of thousands of objects.
Listing 3 demonstrates how to use an ADO query coupled with the ADO Command object's RecordSet.RecordCount property to determine the number of objects in an AD container. Although Listing 3 is slightly more directory- and network-friendly than Listing 2, you'll be disappointed to learn that Listing 3 is almost as slow as Listing 2 because of the way in which the RecordCount property works. When the script reads the RecordCount property, as callout A in Listing 3 shows, the recordset is enumerated under the covers. The net result is identical to that of Listing 2 for all practical purposes. If you're curious why I subtracted 1 in the code at callout A, I did so to compensate for the base container being returned as part of the query results. Including the base container is typical for a Lightweight Directory Access Protocol (LDAP) query in which the scope is set to OneLevel, as is the case with Listing 3.
According to the AD software development kit (SDK), you can use Windows 2003's new msDS-Approx-Immed-Subordinates attribute "to assist the UI with determining how to display the contents of a container." However, the SDK goes on to say the attribute's value can be off by as much as 10 percent on large containers. My experience with msDS-Approx-Immed-Subordinates has been even worse. I've seen the attribute's value off by as much as 30 percent on a container with 100,000 objects. If you need an accurate count, don't use this attribute.
So, you have two accurate but slow solutions and one inaccurate solution. Which one, if any, should you use? If time isn't a concern (i.e., you can afford to let the script run for several hours, if necessary) and you don't need real-time statistics, I suggest that you use Listing 2. I also suggest that you schedule this script to run during nonpeak hours. If time is crucial or you need real-time statistics, you're going to have to be a bit more creative or use a third-party solution.