Search code examples
c#active-directoryprincipalcontext

Find Users by Query inside a Active Directory Group


Given a particular group with a lot of members, I want to query within the group to find members that have a DisplayName match.

The code below is a non-functional example of what I'd like to accomplish. Note that I don't want to load the whole list first then apply the 'where', I can already do that and it is slow because the group is large.

    public static List<Principal> FindUsersOfGroup(string groupName, string displayNameQuery)
    {
        using (var context = new PrincipalContext(ContextType.Machine, Environment.MachineName))
        {
            var search = new GroupPrincipal(context);
            search.SamAccountName = groupName;
            // This where doesn't work, but is what I'm looking for.
            search.Members.Where(m => m.DisplayName == displayNameQuery + "*");

            using (var ps = new PrincipalSearcher(search))
            {
                // Want to get all members that match the query AND belong to the group.
                return ps.FindAll().ToList();
            }
        }
    }

Also, the context is Domain in my real code, I replaced it on purpose.


Solution

  • You can do something like this with the DirectorySearcher class:

    using (DirectoryEntry entry = new DirectoryEntry("LDAP://" + Environment.UserDomainName))
    {
        using (DirectorySearcher searcher = new DirectorySearcher(
            entry,
            string.Format(
                "(&(objectCategory=person)(objectClass=user)(displayName={0}*)(memberof={1}))",
                displayNameQuery,
                groupName)))
        {
    
            searcher.PropertiesToLoad.Add("samAccountname"); //You can specify which properties you want to load. If you don't specify properties, by default you will get a lot of properties. Loading specific properties is better in terms of performance
    
            using (var results = searcher.FindAll())
            {
                foreach (var result in results.Cast<SearchResult>())
                {
                    //Do something with result
                    var properties = result.Properties;
    
                    //Example
                    var samAccountName = properties["samAccountName"][0];
                    //...
                }
            }
        }
    }
    

    groupName in this case is the distinguished name of the group (e.g. CN=Administrators,CN=Builtin,DC=dnb,DC=lab)