Reputation: 2629
When i run the code below to retrieve all groups, subgroups and related users i get a strange error after retrieving some records : I'm expecting to retrieve 90000 Group/subgroup and 250000 users
Error:
System.Runtime.InteropServices.COMException was caught Message=The server is not operational
public static List<Group>getUsers()
{
// create the "context" in which to operate - your domain here,
// as the old-style NetBIOS domain, and the container where to operate in
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "lin.proximus.com");
// define a "prototype" - an example of what you're searching for
// Here: just a simple GroupPrincipal - you want all groups
GroupPrincipal prototype = new GroupPrincipal(ctx);
// define a PrincipalSearcher to find those principals that match your prototype
PrincipalSearcher searcher = new PrincipalSearcher(prototype);
// define a list of strings to hold the group names
List<Group> groupNames = new List<Group>();
int counter = 0;
// iterate over the result of the .FindAll() call
foreach (var gp in searcher.FindAll())
{
// cast result to GroupPrincipal
GroupPrincipal groupPrincipal = gp as GroupPrincipal;
// if everything - grab the group's name and put it into the list
if (groupPrincipal == null) continue;
Group group = new Group();
group.Name = groupPrincipal.Name;
group.Description = groupPrincipal.Description;
AddSubGroups(groupPrincipal, ref group);
AddMemebers(groupPrincipal, ref group);
counter++;
groupNames.Add(group);
Console.WriteLine(counter);
if (counter > 10000)
return groupNames;
}
return groupNames;
}
private static void AddSubGroups(GroupPrincipal gp,ref Group gr)
{
gr.SubCounts = 0;
if (gp.GetGroups().Count() <= 0) return;
gr.SubCounts = gp.GetGroups().Count();
gr.SubGroups = new List<string>();
foreach (var principal in gp.GetGroups())
{
gr.SubGroups.Add(principal.Name);
}
}
private static void AddMemebers(GroupPrincipal gp, ref Group gr)
{
if (gp.GetMembers().Count() <= 0) return;
gr.Users = new List<string>();
foreach (Principal principal in gp.GetMembers())
{
gr.Users.Add(principal.Name);
}
}
Any Idea?
Upvotes: 2
Views: 849
Reputation: 3819
That error could mean any number of things, but I would highly advise [Wireshark'ing][1] the TCP traffic between your machine and the ldap server to get a better feel for what is actually causing it.
If your connection is timing out while the searcher is running, you'll see a [RST, ACK] from your machine right before that error is thrown. This could also go in the reverse, where the target ldap server is forcibly closing your connection before the searcher finishes.
Also, I would advise using the objects and classes available in the lower level DirectoryServices namespace, rather than what the AccountManagement namespace has to offer.
I really dig the LdapConnection and DirectorySearcher objects for this kind of thing, both of which have a ton of flexibility :
LdapConnection ldapConnection = new LdapConnection("lin.proximus.com:389");
ldapConnection.Timeout = 100000;
Setting the PageSize as jeemster had recommended, and the PageTimeLimit :
var directoryEntry = new DirectoryEntry(("LDAP://" + ldapUrl), usrname, password);
var directorySearcher = new DirectorySearcher(directoryEntry)
{
SearchScope = SearchScope.Subtree,
ServerPageTimeLimit = TimeSpan.FromSeconds(100000),
PageSize = 500000
};
Let me know what you find out here.
Upvotes: 1
Reputation: 10986
Looks like you could set the DirectorySearcher.PageSize and do a paged results set. This will typically allow you to beat the server side limit.
I would still try a known LDAP tool (I like Apache Studio) and see if it works. (directory.apache.org/studio)
Upvotes: 2