Get users that are 'memberof' a group
If you can use System.DirectoryServices.AccountManagement
:
var context = new PrincipalContext(ContextType.Domain, "YOUR_DOMAIN_NAME");
using (var searcher = new PrincipalSearcher())
{
var groupName = "YourGroup";
var sp = new GroupPrincipal(context, groupName);
searcher.QueryFilter = sp;
var group = searcher.FindOne() as GroupPrincipal;
if (group == null)
Console.WriteLine("Invalid Group Name: {0}", groupName);
foreach (var f in group.GetMembers())
{
var principal = f as UserPrincipal;
if (principal == null || string.IsNullOrEmpty(principal.Name))
continue;
Console.WriteLine("{0}", principal.Name);
}
}
I have some VB code that'll do it the old way also, but this is definitely simpler with AccountManagement.
Here's the VB code I was referring to (again it isn't pretty but it's functional):
Public Function GetUsersByGroup(de As DirectoryEntry, groupName As String) As IEnumerable(Of DirectoryEntry)
Dim userList As New List(Of DirectoryEntry)
Dim group As DirectoryEntry = GetGroup(de, groupName)
If group Is Nothing Then Return Nothing
For Each user In GetUsers(de)
If IsUserInGroup(user, group) Then
userList.Add(user)
End If
Next
Return userList
End Function
Public Function GetGroup(de As DirectoryEntry, groupName As String) As DirectoryEntry
Dim deSearch As New DirectorySearcher(de)
deSearch.Filter = "(&(objectClass=group)(SAMAccountName=" & groupName & "))"
Dim result As SearchResult = deSearch.FindOne()
If result Is Nothing Then
Return Nothing
End If
Return result.GetDirectoryEntry()
End Function
Public Function GetUsers(de As DirectoryEntry) As IEnumerable(Of DirectoryEntry)
Dim deSearch As New DirectorySearcher(de)
Dim userList As New List(Of DirectoryEntry)
deSearch.Filter = "(&(objectClass=person))"
For Each user In deSearch.FindAll()
userList.Add(user.GetDirectoryEntry())
Next
Return userList
End Function
Public Function IsUserInGroup(user As DirectoryEntry, group As DirectoryEntry) As Boolean
Dim memberValues = user.Properties("memberOf")
If memberValues Is Nothing OrElse memberValues.Count = 0 Then Return False
For Each g In memberValues.Value
If g = group.Properties("distinguishedName").Value.ToString() Then
Return True
End If
Next
Return False
End Function
And usage:
Dim entries = New DirectoryEntry("LDAP://...")
Dim userList As IEnumerable(Of DirectoryEntry) = GetUsersByGroup(entries, "GroupName")
using System.DirectoryServices;
DirectoryEntry objEntry = DirectoryEntry(Ldapserver, userid, password);
DirectorySearcher personSearcher = new DirectorySearcher(objEntry);
personSearcher.Filter = string.Format("(SAMAccountName={0}", username);
SearchResult result = personSearcher.FindOne();
if(result != null)
{
DirectoryEntry personEntry = result.GetDirectoryEntry();
PropertyValueCollection groups = personEntry.Properties["memberOf"];
foreach(string g in groups)
{
Console.WriteLine(g); // will write group name
}
}
I originally used a method similar to what you have posted and it took about 12 minutes to run through my entire company's AD and get the results. After switching to this method, it takes about 2 minutes. You will need to use the ldapserver address where I wrote ldapserver and the userid and password as well and username is the SAMAccountName for the person you're looking up.
If you check HERE you can do the following:
DirectoryEntry group = new DirectoryEntry("LDAP://CN=foo-group,DC=Cmp,DC=COM");
foreach(object dn in group.Properties["member"] )
//do whatever