Active Directory Subgroups search
-
29-10-2019 - |
Question
I need have a root AD group and need to enumerate through all its subgroups. I have a code, that connects to the AD server and tries to retrieve subgroups list.
Here's the code:
private IEnumerable<SearchResult> GetSubGroups(string groupId)
{
using (var searcher = new DirectorySearcher(new DirectoryEntry(adServerName, adLogin, adPassword)))
{
searcher.Filter = string.Format("(&(objectClass=group)({0}))", groupId);
//Get the Root Group
var result = searcher.FindOne();
object resultMembers = result.GetDirectoryEntry().Invoke("Members", null);
foreach(var member in ((IEnumerable) resultMembers))
{
var memberEntry = new DirectoryEntry(member);
var subgroupsSearcher = new DirectorySearcher(memberEntry);
subgroupsSearcher.Filter = "(objectClass=group)";
subgroupsSearcher.PropertiesToLoad.Add("samaccountname");
subgroupsSearcher.PropertiesToLoad.Add("name");
var foundSubGroupResult = subgroupsSearcher.FindOne();
...
}
return new List<SearchResult> {result};
}
}
When enumerating throught the Invoke("Members", null) results I create another DirectoryEntry for each result.
The problem is, that when a subgroupSearcher.FindOne()
is called, it ends up with a DirectoryServicesCOMException
.
Here's the exception stack trace:
at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
at System.DirectoryServices.DirectoryEntry.Bind()
at System.DirectoryServices.DirectoryEntry.get_AdsObject()
at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
at System.DirectoryServices.DirectorySearcher.FindOne()
...other methods...
Exception's Message property says: "An operations error occured"
I've logged the ErrorCode, it's -2147016672
I also attempted to initialize UserName property implicitly, when creating the DirectoryEntry from the subgroup object:
foreach(var member in ((IEnumerable) resultMembers))
{
var memberEntry = new DirectoryEntry(member);
memberEntry.Username = adLogin;
var subgroupsSearcher = new DirectorySearcher(memberEntry)
...
}
But it gave the same result.
What I'm doing wrong? Any help is appreciable.
Solution
Not sure why you're calling Invoke("members"). You'd want to just have the DirectorySearcher give you back the member attribute of the group. Two things you need to deal with:
- Attribute value ranging - http://www.netid.washington.edu/documentation/enumeratingLargeGroups.aspx
- Nesting loops - your code will need to track groups you have already expanded so you don't do it over and over
OTHER TIPS
Here is a piece of code. It allow to use a recursive filter see Search Filter Syntax to retreive all the members of a group of the class 'group
'(the thing you call subgroups)
static void Main(string[] args)
{
/* Connection to Active Directory
*/
string sFromWhere = "LDAP://WM2008R2ENT:389/dc=dom,dc=fr";
DirectoryEntry deBase = new DirectoryEntry(sFromWhere, "dom\\jpb", "test.2011");
/* To find all the groups member of groups "Grp1" :
* Set the base to the groups container DN; for example root DN (dc=societe,dc=fr)
* Set the scope to subtree
* Use the following filter :
* (member:1.2.840.113556.1.4.1941:=CN=Grp1,OU=MonOu,DC=X)
* coupled with a AND Bit filter on userAccountControl
*/
DirectorySearcher dsLookFor = new DirectorySearcher(deBase);
dsLookFor.Filter = "(&(memberof:1.2.840.113556.1.4.1941:=CN=MonGrpSec,OU=MonOu,DC=dom,DC=fr)(objectClass=group))";
dsLookFor.SearchScope = SearchScope.Subtree;
dsLookFor.PropertiesToLoad.Add("cn");
SearchResultCollection srcGroups = dsLookFor.FindAll();
/* Just to write some result
*/
foreach (SearchResult srcGroup in srcGroups)
{
Console.WriteLine("{0}", srcGroup.Path);
}
Console.ReadLine();
}