I have a very strange problem...I have a function which works in 99/100 times...But unfortunately I have noticed one group which generates me some problems.
The worst thing is that I don't see anything special in it...name is nomral, I have access to list it...But my program doesn't return any results...It threat it as if it was empty...
But I know its not true:

String listGroupUsers(string Name)
        {
            try
            {
                SearchResult result;
                DirectorySearcher search = new DirectorySearcher();
                search.Filter = String.Format("(cn={0})", Name);
                search.PropertiesToLoad.Add("member");
                result = search.FindOne();
                if (result == null)
                {
                    search.Filter = String.Format("(samAccountName=" + Name + ")");
                    result = search.FindOne();
                    if (result == null)
                    {
                        tempreport1.Add("ERROR: Input name couldn't be found in AD");
                        return "ERROR: Input name couldn't be found in AD"; 
                    }
                }
                StringBuilder userList = new StringBuilder();
                if (result != null)
                {
                    for (int counter = 0; counter < result.Properties["member"].Count; counter++)
                    {
                        string user = (string)result.Properties["member"][counter];
                        string property = getproperty("LDAP://" + user, "displayname");
                        if (property=="No record found") // grupy nie maja display name - wiec jak sie na nich wywali ma wyciagnac win2000 name
                        {  
                        property = getproperty("LDAP://" + user, "samAccountName");
                        }
                        userList.Append(property);
                        userList.Append("\r\n");
                    }
                }
                tempreport1.AddRange(userList.ToString().Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList());
                return userList.ToString();
            }
            catch (Exception)
            {
                return " ";
            }
        }

The most interesting thing is that the most important condition is fulfilled (23rd line):

if (result != null)

so there ARE results but...when I try to show any results with line:

result.Properties["member"][X]
X = any number

it returns null...

result.Properties["member"].Count

is 0..so the for loop in my program isn't launched at all... WHY?...I am really curious because that group count about 3000 members...

Dani AI

Generated

This is almost always an Active Directory behaviour, not an empty group. Large multi‑valued attributes (like a group’s member list) are returned by the server using LDAP "range retrieval" attributes such as member;range=0-1499 instead of a plain member. In .NET 3.5 the DirectoryServices layer does not normalize those ranged names back to member, so result.Properties["member"] can appear empty. correctly noticed the Framework 4.0 runtime handles this better; on 3.5 the member values must be pulled out of the ranged attribute names or requested in ranges explicitly. Another possible cause is querying a Global Catalog (port 3268) which does not hold all attributes — that also makes member missing.

Quick diagnostic: list what the search actually returned (property names) to see whether member;range= attributes are present:

// after search.FindOne() returns 'result'
foreach (string pname in result.Properties.PropertyNames)
{
    Console.WriteLine(pname); // will show "member;range=0-1499" etc if ranged retrieval is used
}

If ranged attributes are present, collect members by requesting successive ranges until the server returns the last range (attribute name ends with "-*"). Example approach for .NET 3.5 (adapt to error handling and resource disposal as needed):

List<string> GetGroupMembersByRange(string groupDn)
{
    var members = new List<string>();
    using (var entry = new DirectoryEntry("LDAP://" + groupDn))
    using (var ds = new DirectorySearcher(entry))
    {
        int step = 1500;
        int low = 0;
        while (true)
        {
            string rangeAttr = $"member;range={low}-{low + step - 1}";
            ds.PropertiesToLoad.Clear();
            ds.PropertiesToLoad.Add(rangeAttr);
            var res = ds.FindOne();
            if (res == null) break;
            string returned = res.Properties.PropertyNames.Cast<string>()
                                .FirstOrDefault(n => n.StartsWith("member", StringComparison.OrdinalIgnoreCase));
            if (returned == null) break;
            foreach (var v in res.Properties[returned]) members.Add(v.ToString());
            if (returned.EndsWith("-*")) break;
            var rng = returned.Substring(returned.IndexOf("range=", StringComparison.OrdinalIgnoreCase) + 6);
            int end = int.Parse(rng.Split('-')[1].TrimEnd('*'));
            low = end + 1;
        }
    }
    return members;
}

To report nested groups (instead of a flat list), walk the membership tree and record parent→child relations: fetch direct members (use a range-aware fetch as above), check if a member DN is a group (inspect objectClass for "group" or use PrincipalType), and recurse while keeping a visited set to avoid cycles. If upgrading to .NET 4+ is feasible, the AccountManagement API simplifies member enumeration, but explicit recursion is still required to record which group caused a nested member to appear. Performance note: large groups and deep recursion can be expensive; perform operations off the UI thread and limit recursion depth or aggregate results incrementally.

can it be a bug? because for me the code is very OK..

Ok I have found out that this is bug, it was corrected in Framework 4.0. But I need to use FM 3.5

I have found a code:

    String listGroupUsers(string GroupName)
    {
        PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domain);
        GroupPrincipal grp = GroupPrincipal.FindByIdentity(ctx, IdentityType.Name, GroupName);

        if (grp != null)
        {
            foreach (Principal p in grp.GetMembers(true))
            {
                AddMessage(p.Name + "\r\n", Color.DarkGreen, FontStyle.Regular);
            }


            grp.Dispose();
            ctx.Dispose();
        }
        return "";
    }

The problem is that this function returns all members, even in nested groups...Its nice, but I would like to be informed what group is nested (beside seeing members only).
IS there any way to do that?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.