Search code examples
c#active-directoryldap

How can I retrieve just users from the Active Directory, not groups


I am having this code that returns list of users and groups from the Active Directory

public ArrayList GetADGroupUsers(string groupNames)
{

    string[] strGrpNames = groupNames.Split(new char[] { ',' });
    string strTeamList = string.Empty;
    ArrayList userNames = new ArrayList();            
    string ADPassword = ConfigurationManager.AppSettings["ADPassword"];
    IAAccess_Transaction.drms_dataaccess drmsda = new IAAccess_Transaction.drms_dataaccess();
      
    string domainAndUsername = ConfigurationManager.AppSettings["domain"] + @"\" + ConfigurationManager.AppSettings["ADUserName"];
    string decriptedADPassword = drmsda.Decrypt(ADPassword);
    DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, decriptedADPassword);

    //Bind to the native AdsObject to force authentication.
    object obj = entry.NativeObject;

    DirectorySearcher search = new DirectorySearcher(entry);

    foreach (string strGrp in strGrpNames)
    {
        search.Filter = String.Format("(cn={0})", strGrp);
        search.PropertiesToLoad.Add("member");

        SearchResult result = search.FindOne();

        if (result != null)
        {
            for (int counter = 0; counter <
                     result.Properties["member"].Count; counter++)
            {
                string user = (string)result.Properties["member"][counter];
                userNames.Add(user);
            }
        }
    }
    return userNames;
}

This code retrieves BOTH, users AND group as shown on the screenshot. How can I modify this code to retrieve JUST users, NOT groups?

enter image description here


Solution

  • In order to include the nested group members, you need to lookup each entry and find out if it is a group or user. If it is a group, you can add to the groups you are already processing. Since C#/.Net doesn't have a built-in Deque class, I used LinkedList<T> instead.

    public List<string> GetADGroupUsers(string groupNames) {
        LinkedList<string> strGrpNames = new(groupNames.Split(','));
        List<string> userNames = new();
        string ADPassword = ConfigurationManager.AppSettings["ADPassword"];
        string domainAndUsername = ConfigurationManager.AppSettings["domain"] + @"\" + ConfigurationManager.AppSettings["ADUserName"];
        string decryptedADPassword = drmsda.Decrypt(ADPassword);
        DirectoryEntry entry = new(_path, domainAndUsername, decryptedADPassword);
    
        //Bind to the native AdsObject to force authentication.
        object obj = entry.NativeObject;
    
        DirectorySearcher groupSearcher = new(entry);
        groupSearcher.PropertiesToLoad.Add("member");
        DirectorySearcher userSearcher = new(entry);
        userSearcher.PropertiesToLoad.Add("groupType");
        while (strGrpNames.Count > 0) {
            string strGrp = strGrpNames.First();
            strGrpNames.RemoveFirst();
            groupSearcher.Filter = $"(cn={strGrp})";
            SearchResult result = groupSearcher.FindOne();
    
            if (result != null) {
                var members = result.Properties["member"];
                for (int counter = 0; counter < members.Count; ++counter) {
                    var user = (string)members[counter];
                    var userCN = user.Substring(user.IndexOf('=')+1).Substring(0,user.IndexOf(',')-3);
                    userSearcher.Filter = $"(cn={userCN})";
                    SearchResult userProperties = userSearcher.FindOne();
                    var userGroupType = userProperties.Properties["groupType"];
                    if (userGroupType != null && userGroupType.Count > 0) // group
                        strGrpNames.AddFirst(userCN);
                    else
                        userNames.Add(user);
                }
            }
        }
        return userNames;
    }