29

I'm trying to get all users of a particular group in AD, then return a list of Employees as mapped to properties in my Employee class. I have:

My Filter is producing no results - what should it be?

Also, I tried the first solution here: List of users in specific Active Directory Distribution Group, but I need details such as mobile, extension, etc. which I couldn't get with that method.

public static List<Employee> CreateEmployeeList(string department)
{
    List<Employee> employees = new List<Employee>();
    string filter = string.Format("(&(ObjectClass=person)(memberOf=CN={0},OU=Users & Groups,OU=Blah,DC=Blah,DC=Blah,DC=Blah))", department);

    DirectoryEntry adRoot = new DirectoryEntry("LDAP://" + domain, null, null, AuthenticationTypes.Secure);
    DirectorySearcher searcher = new DirectorySearcher(adRoot);
    searcher.SearchScope = SearchScope.Subtree;
    searcher.ReferralChasing = ReferralChasingOption.All;
    searcher.Filter = filter;
    SearchResultCollection results = searcher.FindAll();

    foreach (SearchResult user in results)
    {
        // do whatever you need to do with the entry

        if (user != null)
        {
            UserDirectoryEntry = user.GetDirectoryEntry();
            string displayName = GetUserProperty("displayName");
            string firstName = GetUserProperty("givenName");
            string lastName = GetUserProperty("sn");
            string email = GetUserProperty("mail");
            string tel = GetUserProperty("telephonenumber");
            string extension = GetUserProperty("ipphone");
            string mobile = GetUserProperty("mobile");
            string title = GetUserProperty("description");
            employees.Add(new Employee{ FullName = displayName, FirstName = firstName, Surname = lastName, Email = email.ToLower(), Telephone = tel, Extension = extension, Mobile = mobile, JobTitle = title });
        }
    }
    return employees;
}
ataravati
  • 8,891
  • 9
  • 57
  • 89
raklos
  • 28,027
  • 60
  • 183
  • 301

5 Answers5

65
using (var context = new PrincipalContext(ContextType.Domain, "domainName"))
{
    using (var group = GroupPrincipal.FindByIdentity(context, "groupName"))
    {
        if (group == null)
        {
            MessageBox.Show("Group does not exist");
        }
        else
        {
            var users = group.GetMembers(true);
            foreach (UserPrincipal user in users)
            {
                 //user variable has the details about the user 
            }
        } 
    }
}
ataravati
  • 8,891
  • 9
  • 57
  • 89
Dalton
  • 1,334
  • 1
  • 11
  • 19
  • 1
    perfect solution, thanks! btw. there is no need to put "domainName" in .NET Framework 4.5 – Tom Nov 12 '13 at 09:46
  • 8
    Requires reference to System.DirectoryServices.AccountManagement. – Rok Strniša Dec 11 '13 at 10:39
  • 1
    Unfortunately, this only returns group members that are User objects and does not return group members that are Contact objects. Is there a way to return ALL group members? – BardMorgan Mar 08 '16 at 12:54
  • It would surely be helpful to include what "using" statements and references you need to make for this to work. – Brad May 13 '16 at 17:20
  • 2
    Also, members can be users **OR GROUPS**. Won't this throw an exception if **var** "users" contains a group ? – Stefan Steiger Jul 08 '16 at 09:12
  • 1
    @StefanSteiger : the `true` flag in `GetMembers()` specify the `recursive search`, therefore no error is thrown. – Muflix Sep 29 '16 at 15:17
  • It will throw an exception if the group contains a **computer**. You have to test if the member type is `ComputerPrincipal` or `UserPrincipal`. – Alix Sep 22 '17 at 00:49
15

This should return all Active Directory Users in a group.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;

namespace ADQuery
{
    class Program
    {
        static void Main(string[] args)
        {
            GetListOfAdUsersByGroup("domain", "group");
            Console.ReadLine();
        }

        public static void GetListOfAdUsersByGroup(string domainName, string groupName)
        {
            DirectoryEntry entry = new DirectoryEntry("LDAP://DC=" + domainName + ",DC=com");
            DirectorySearcher search = new DirectorySearcher(entry);
            string query = "(&(objectCategory=person)(objectClass=user)(memberOf=*))";
            search.Filter = query;
            search.PropertiesToLoad.Add("memberOf");
            search.PropertiesToLoad.Add("name");

            System.DirectoryServices.SearchResultCollection mySearchResultColl = search.FindAll();
            Console.WriteLine("Members of the {0} Group in the {1} Domain", groupName, domainName);
            foreach (SearchResult result in mySearchResultColl)
            {
                foreach (string prop in result.Properties["memberOf"])
                {
                    if (prop.Contains(groupName))
                    {
                        Console.WriteLine("    " + result.Properties["name"][0].ToString());
                    }
                }
            }
        }
    }
}

Good Luck!

Gaeburider
  • 158
  • 1
  • 12
Jive Boogie
  • 1,265
  • 1
  • 12
  • 20
  • ot sure what (!(userAccountControl:1.2.840.113556.1.4.803:=2))(&(mail=*) is meant to mean - also i need to filter by group – raklos Oct 27 '11 at 13:59
  • Sorry was in a rush and read your question wrong I posted some code that should be more helpful. – Jive Boogie Oct 27 '11 at 15:16
3

The following code will search through nested domain local groups and/or global groups recursively to find users. You can modify this to look through any order of groups to suit what you need or to return any kind of group that you want.

// Set the list to return and get the group we are looking through.
List<UserPrincipal> list = new List<UserPrincipal>();
GroupPrincipal group = GroupPrincipal.FindByIdentity(new PrincipalContext(/* connection info here */), ((groupName.Length > 0) ? groupName : this.Properties.Name));

// For each member of the group add all Users.
foreach (Principal princ in group.Members)
{
    /*
    To change what you are looking for or how you are looking for it, 
    simply change some of the following conditions to match what you want.
    */

    // If this member is a User then add them.
    if (princ.StructuralObjectClass == "user")
    {
        list.Add(UserPrincipal.FindByIdentity(new PrincipalContext(/* connection info here */), princ.Name);
    }

    // If we are looking recursively and this member is a GL_Group then get the Users in it and add them.
    if (recursive && (princ.StructuralObjectClass == "group") && (((GroupPrincipal)princ).GroupScope == GroupScope.Global))
    {
        list.AddRange(this.GetUsers(true, princ.Name));
    }
}
return list;
Joshua G
  • 2,086
  • 3
  • 19
  • 22
3

Building on the example by Dalton, here's concise code to get group's usernames:

static SortedSet<string> GetUsernames(string domainName, string groupName) {
  using (var pc = new PrincipalContext(ContextType.Domain, domainName))
  using (var gp = GroupPrincipal.FindByIdentity(pc, groupName))
    return gp == null ? null : new SortedSet<string>(
      gp.GetMembers(true).Select(u => u.SamAccountName));
}
Community
  • 1
  • 1
Rok Strniša
  • 6,781
  • 6
  • 41
  • 53
0

In this post I wrote something working in an ActiveDirectory 2003 ans 2008 R2. I use Microsoft LDAP_MATCHING_RULE_IN_CHAIN. This service use DirectoryServices. Be careful in this code as there is a double search.

But you can also do it using Managing Directory Security Principals in the .NET Framework 3.5. You can read this other post. You have to get a GroupPrincipal and you are looking for Members property. It also exists other entries in StackOverflow.

Community
  • 1
  • 1
JPBlanc
  • 70,406
  • 17
  • 130
  • 175