Printout Header
RSS Feed

How to find all members of an Active Directory group


In Active Directory Scripts the members of a group are searched often by binding to the regarding group object and evaluating it's API property members or LDAP attribute member - or by evaluating the 'opposite' user attribute memberOf. However, this is not exactly the same, because group memberships can be implemented not only through this attribute pair, but also in the form of 'primary groups', this is set in the user attribute primaryGroupID. So the actual group membership of a directory object consists always of two attributes! The mentioned property of the primary group is actually only needed if Mac or Posix clients log onto the domain.

By default, for new users the primary group property is set to 'domain users', so it is often not important that this group membership is missing in the basic evaluation of the member values. However, if other groups are registered as a primary group, this traditional way of membership evaluation is not accurate enough! Therefore, this article describes next to the qick-and-dirty method also how to determine a complete list of the members of a group.

To find the members of a group, we must first identify the full LDAP Distinguished Name (DN) of the regarding group object. The necessary steps for this are described in detail in the SelfADSI article 'Name Translation: How to identify the LDAP path of a user'.

For the actual search, we use the Active Directory memberOf attribute with an appropriate LDAP filter. To really find all users that you have to pay attention to the attribute primaryGroupID also. This is the relative ID (RID) of the primary group for that user - and this primary group doesn't appears in the memberOf attribute list! Fortunately, you don't have to perform a complete SID evaluation and calculation (SelfADSI article 'Microsoft Security Descriptor (SID) attributes') - you can search for the appropriate primaryGroupToken attribute of that group instead. By the way: This attribute is an operational attribute and must be requested explicitly when reading the group object.


Search Group Members - quick and dirty


First, we consider a script that evaluates the membership on the basis of a given group distinguished name (DN), the property "Primary group" is ignored - in many cases a complete list of group members can be obtained:

groupDN = "cn=GroupA,ou=Gruppen,dc=example,dc=com" 'insert your own group DN here Set group = GetObject("LDAP://" & groupDN) For Each memberDN In group.member WScript.Echo memberDN Next

Search Group Members in the own Domain


And now the careful method involving the primary group membership. This script finds all members of a group in the domain in which the current user (which the script is running) is a member. It also assumes that only the group name itself and not the distinguished name is known:

groupName = "GroupA" 'insert your own group name here Set rootDSE = GetObject("LDAP://rootDSE") 'detect the own domain domainDN = rootDSE.Get("defaultNamingContext") 'detect the DN and the RID of the group ldapFilter = "(sAMAccountName=" & groupName & ")" Set ado = CreateObject("ADODB.Connection") ado.Provider = "ADSDSOObject" ado.Open "ADSearch" Set objectList = ado.Execute("<LDAP://" & domainDN & ">;" & ldapFilter & _ ";distinguishedName,primaryGroupToken;subtree") groupDN = objectList.Fields("distinguishedName") groupRID = objectList.Fields("primaryGroupToken") 'search the members ldapFilter = "(|(memberOf=" & groupDN & ")(primaryGroupID=" & groupRID & "))" Set ado = CreateObject("ADODB.Connection") ado.Provider = "ADSDSOObject" ado.Open "ADSearch" Set objectList = ado.Execute("<LDAP://" & domainDN & ">;" & ldapFilter & _ ";distinguishedName,samAccountName,displayname,userPrincipalName;subtree") While Not objectList.EOF userDN = objectList.Fields("distinguishedName") logonName = objectList.Fields("samAccountName") On Error Resume Next displayName = "" : displayName = objectList.Fields("displayname") logonNameUPN = "" : logonNameUPN = objectList.Fields("userPrincipalName") On Error Goto 0 WScript.Echo logonName & ";" & logonNameUPN & ";" & displayName & ";" & userDN objectList.MoveNext Wend

Search Group Members in the entire Forest


This script finds all members of a group in the entire forest in which the current user (which the script is running) is a member. The group itself has to be in the same domain as the user who runs this script. We have to do two separate searches for memberOf (performed in the entire forest) and primaryGroupID (only in the own domain). The primary group of a user must in fact always be a group of its own domain.

groupName = "GroupA" 'insert your own group name here Set rootDSE = GetObject("LDAP://rootDSE") 'detect the own domain domainDN = rootDSE.Get("defaultNamingContext") Set aoi = CreateObject("ADSystemInfo") 'detect the forest search base string gcBase = aoi.ForestDNSName 'detect the DN and the RID of the group ldapFilter = "(sAMAccountName=" & groupName & ")" Set ado = CreateObject("ADODB.Connection") ado.Provider = "ADSDSOObject" ado.Open "ADSearch" Set objectList = ado.Execute("<LDAP://" & domainDN & ">;" & ldapFilter & _ ";distinguishedName,primaryGroupToken;subtree") groupDN = objectList.Fields("distinguishedName") groupRID = objectList.Fields("primaryGroupToken") '______________________________________________________ search members -> memberOf search in the entire forest ldapFilter = "(memberOf=" & groupDN & ")" Set objectList = ado.Execute("<GC://" & gcBase & ">;" & ldapFilter & _ ";distinguishedName,samAccountName,displayname,userPrincipalName;subtree") While Not objectList.EOF userDN = objectList.Fields("distinguishedName") logonName = objectList.Fields("samAccountName") On Error Resume Next displayName = "" : displayName = objectList.Fields("displayname") logonNameUPN = "" : logonNameUPN = objectList.Fields("userPrincipalName") On Error Goto 0 WScript.Echo logonName & ";" & logonNameUPN & ";" & displayName & ";" & userDN objectList.MoveNext Wend '______________________________________________________ search members -> primaryGroupID search in the own domain ldapFilter = "(primaryGroupID=" & groupRID & ")" Set objectList = ado.Execute("<LDAP://" & domainDN & ">;" & ldapFilter & _ ";distinguishedName,samAccountName,displayname,userPrincipalName;subtree") While Not objectList.EOF userDN = objectList.Fields("distinguishedName") logonName = objectList.Fields("samAccountName") On Error Resume Next displayName = "" : displayName = objectList.Fields("displayname") logonNameUPN = "" : logonNameUPN = objectList.Fields("userPrincipalName") On Error Goto 0 WScript.Echo logonName & ";" & logonNameUPN & ";" & displayName & ";" & userDN objectList.MoveNext Wend

Gruppenmitglieder suchen in einem fremden Forest (mit Anmeldung)


This script finds all members of a specified group in the entire forest. Use the matching data for your desired Forest, or the domain where the regarding group. For this search, we need a global catalog server which is DC for the domain where the group is located. You could also use other credentials for the search (username and password):

domainDN = "DC=sub,DC=example,DC=com" 'specify the domain where the group is located rootDN = "DC=example,DC=com" 'specify the LDAP path for the root domain serverName = "192.168.0.66" 'specify the IP address or name of a global catalog 'this GC has to be DC of the domain where the group is userName = InputBox("Enter user name","Credentials") 'you could also just use a static username instead, like "EXAMPLE\userXYZ" password = InputBox("Enter password","Credentials") 'you could also just use a static password instead, like "P@ssw0rd" groupName = "GroupA" 'insert your own group name here 'detect the DN and the RID of the group ldapFilter = "(sAMAccountName=" & groupName & ")" Set ado = CreateObject("ADODB.Connection") ado.Provider = "ADSDSOObject" ado.Properties("User ID") = userName ado.Properties("Password") = password ado.Properties("Encrypt Password") = True ado.Open "ADSearch" Set objectList = ado.Execute("<LDAP://" & serverName & "/" & domainDN & ">;" & ldapFilter & _ ";distinguishedName,primaryGroupToken;subtree") groupDN = objectList.Fields("distinguishedName") groupRID = objectList.Fields("primaryGroupToken") '______________________________________________________ search members -> memberOf search in the entire forest ldapFilter = "(memberOf=" & groupDN & ")" Set objectList = ado.Execute("<GC://" & serverName & "/" & domainDN & ">;" & ldapFilter & _  ";distinguishedName,samAccountName,displayname,userPrincipalName;subtree") While Not objectList.EOF userDN = objectList.Fields("distinguishedName") logonName = objectList.Fields("samAccountName") On Error Resume Next displayName = "" : displayName = objectList.Fields("displayname") logonNameUPN = "" : logonNameUPN = objectList.Fields("userPrincipalName") On Error Goto 0 WScript.Echo logonName & ";" & logonNameUPN & ";" & displayName & ";" & userDN objectList.MoveNext Wend '______________________________________________________ search members -> primaryGroupID search in the domain ldapFilter = "(primaryGroupID=" & groupRID & ")" Set objectList = ado.Execute("<LDAP://" & serverName & "/" & domainDN & ">;" & ldapFilter & _  ";distinguishedName,samAccountName,displayname,userPrincipalName;subtree") While Not objectList.EOF userDN = objectList.Fields("distinguishedName") logonName = objectList.Fields("samAccountName") On Error Resume Next displayName = "" : displayName = objectList.Fields("displayname") logonNameUPN = "" : logonNameUPN = objectList.Fields("userPrincipalName") On Error Goto 0 WScript.Echo logonName & ";" & logonNameUPN & ";" & displayName & ";" & userDN objectList.MoveNext Wend
s