Two
VBScript programs, and one PowerShell script, to document all members of a group
are linked on this page. The members can be users,
contacts,
computers, or other groups.
The LDAP provider is used to bind to the group.
Nested group members are revealed.
The first VBScript program
also includes members that have the group, or any nested group, designated as their
"Primary Group".
The program is designed to be run at a command prompt with the cscript host. The output can be
redirected to a text file. The Distinguished Name of the group is passed to the program as a
parameter. For example:
cscript //nologo EnumGroup.vbs "cn=Sales,ou=West,dc=MyDomain,dc=com" > Sales.txt
If the Distinguished Name passed to the program has a character that must be escaped, such as a comma, be sure to escape the character with the backslash escape character, "\". The characters that must be escaped are:
, \ / # + < > ; " =
This program should work on any 32 or 64-bit Windows client that can log onto the domain. Windows NT
and Windows 98/95 clients should have DSClient installed. If DSClient is not installed, they
need WSH and ADSI installed. The program has been revised to document the
Distinguished Names of the members, instead of the sAMAccountName (pre-Windows 2000 name). This was done because members can be contacts, and Active Directory contact objects do not have a sAMAccountName value. If you are
sure no members will be contact objects, you can substitute sAMAccountName
for distinguishedName in the script.
EnumGroup.txt <<-- Click here to view or download the program
A PowerShell script that performs the same function is linked below. This
should work in PowerShell V1 or V2.
PSEnumGroup.txt <<-- Click here to view or download the program
The programs linked above must bind to all member objects in the group in
order to check if the member is a group. If the member is a group, the
method that enumerates direct members of the group is called recursively. If
the method was called recursively for all members, regardless of class,
errors would be raised when any members are not groups.
The second program does not bind to any objects in Active Directory. This
should make it faster in many cases.
Instead, ADO is used to query Active Directory for all group objects and
their member attribute. The member attribute is a collection of the
Distinguished Names (DN's) of all direct members of the group. The second
program can only output the DN's of all members. Any other attributes would
require binding to all member objects, which would slow down the program.
The recordset that is retrieved has one row for each group in Active
Directory, with the DN of the group and the member collection. The program
disconnects the recordset so we can filter the recordset on group DN. The
program first filters on the DN of the group specified and a subroutine
enumerates all DN's in the member collection (the DN of all direct members
of the group). For each member, the subroutine is called recursively,
passing the DN of the member. We do not know if the member is a group, but
it doesn't matter. When the subroutine filters on a DN that is not a group,
the recordset is empty (since the recordset only has groups) and the subroutine exits immediately, so there is no
error.
While the recordset returned by this method can be very large, all of the
manipulations happen in memory, which is very fast. The speed of this
program compared to the one above will depend on the number of groups in
Active Directory and the number of members in the group. However, in most
cases, it seems to be faster, especially if the group has more than a few
members. This program does not reveal any
"Primary Group" memberships.
EnumGroup3.txt <<-- Click here to view or download the program
If
the group (or any nested groups) has more than 1500 members, then this
program must be revised to use ADO range limits. The page "Document Large
Group" demonstrates how to do this.