0

I am new to stackoverflow as a member, although I follow this a lot :) My code which connects to active directory to get the members of a functional group, gives me only 1490 odd members out of 1680 odd members actually in the list. I have searched a lot on Stackoverflow and on Internet, but I have not found out answer to why the code would result in incomplete list. Could, anyone please give me any pointers on this. Thanks :)

Here is the code which connects to the Active Directory to retrieve the data:

    public static DataTable GetAdUsers(string configSection)
    {

        DataRow dr; 
        Hashtable ADGroups = (Hashtable)ConfigurationManager.GetSection(configSection);
        string adGroup;
        string adGroupDesc;
        string sApplication;
        string sLast_Login;
        string sAccount_owner;
        string sPath;

        DataTable dt = new DataTable();

        sApplication = "Application";
        dt.Columns.Add(sApplication);

        dt.Columns.Add("Profile", Type.GetType("System.String"));
        dt.Columns.Add("Account Name", Type.GetType("System.String"));

        sLast_Login = "Last Login";
        dt.Columns.Add(sLast_Login);

        sAccount_owner = "Account Owner";
        dt.Columns.Add(sAccount_owner);

        sPath = "Path";
        dt.Columns.Add(sPath);

        string domainName = "myDomain";

        PrincipalContext pcRoot = new PrincipalContext(ContextType.Domain, domainName);
        IDictionaryEnumerator adGroupEnumerator = ADGroups.GetEnumerator();

        while (adGroupEnumerator.MoveNext())
        {
            adGroup = adGroupEnumerator.Key.ToString();
            adGroupDesc = adGroupEnumerator.Value.ToString();

            GroupPrincipal grp = GroupPrincipal.FindByIdentity(pcRoot, IdentityType.SamAccountName, adGroup); 
            System.DirectoryServices.DirectoryEntry de = (System.DirectoryServices.DirectoryEntry)grp.GetUnderlyingObject();
            foreach (string sDN in de.Properties["member"])
            {
                System.DirectoryServices.DirectoryEntry deMember = new System.DirectoryServices.DirectoryEntry("LDAP://" + sDN.ToString());
                try
                {
                    dr = dt.NewRow();

                    string output1;
                    string subStringE1 = "DC=";
                    int length1 = de.Path.ToString().Length;
                    int length0 = de.Path.ToString().IndexOf(subStringE1);
                    string str1 = de.Path.ToString().Substring(length0, length1 - length0);
                    string subStringE2 = ",DC";
                    int length2 = str1.ToString().IndexOf(subStringE2);
                    output1 = str1.ToString().Substring(3, length2 - 3);

                    dr["Application"] = "Application";
                    dr["Profile"] = adGroupDesc;

                    string AccountName = deMember.Properties["samAccountName"].Value.ToString();

                    dr["Account Name"] = deMember.Properties["samAccountName"].Value.ToString();
                    dr["Last Login"] = "";
                    dr["Account Owner"] = deMember.Properties["givenName"].Value.ToString() + @"-" + deMember.Properties["sn"].Value.ToString();

                    string Path = output1 + @"\" + adGroup + @"\" + deMember.Properties["samAccountName"].Value.ToString();

                    Console.WriteLine(Path);
                    dr["Path"] = output1 + @"\" + adGroup + @"\" + deMember.Properties["samAccountName"].Value.ToString();

                    dt.Rows.Add(dr);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error occured for user name" + sDN + "\n" + ex.Message);
                }
            }
        }
        return dt;
    }
}
svick
  • 236,525
  • 50
  • 385
  • 514
Ashutosh
  • 25
  • 1
  • 12
  • So you're using the .NET 3.5 `PrincipalContext` and all - then **why** are you switching back to the old-style .NET 2.0 `DirectoryEntry` once you have the member's name?? Doesn't make any sense at all and makes things a lot more cumbersome! You already have a `GroupPrincipal grp` - why aren't you using it's `.GetMembers()` call to get the members of the group? Would be **much easier!** – marc_s Jun 17 '12 at 08:17
  • Hi Marc, do u have any pointers/links on the same. Most of the seacrh results I have received have been on .NET 2.0. Also Afifi's link in Msdn is also on .NET 2.0. – Ashutosh Jun 17 '12 at 09:24
  • See this MSDN magazine article: [Managing Directory Security Principals in the .NET Framework 3.5](http://msdn.microsoft.com/en-us/magazine/cc135979.aspx) – marc_s Jun 17 '12 at 09:25
  • Marc, is there a waay using .NET 3.5 or 4.0, where I can retirve the search beyong 1500 users? I saw your post in http://stackoverflow.com/questions/3488394/c-sharp-active-directory-services-findall-returns-only-1000-entries, but DirectorySearcher.PageSize or DirectorySearcher.PageLimit do not seem to work with .NET 4.0 – Ashutosh Jun 17 '12 at 10:21

3 Answers3

0

Because of the default limit of SizeLimit, you're probably only getting around the 1,490 objects or so. To fix that you need to "page" through the results.

Just use the code referenced at Enumerating Members in a Large Group .

M Afifi
  • 4,645
  • 2
  • 28
  • 48
  • Thanks a lot Afifi :) Just working on the same. The link is very useful – Ashutosh Jun 17 '12 at 08:11
  • The link is quite useful, but groupMember.FindOne() is resulting in an unknown error. – Ashutosh Jun 17 '12 at 08:54
  • But when I am using the code provided in the link, I am getting the error "error occurred for user name member; range = 0-*" – Ashutosh Jun 17 '12 at 10:13
  • @Ashutosh the code only works obviously if the active directory object has a member property. It won't work otherwise – M Afifi Jun 18 '12 at 07:52
  • Hi Afifi, the code did not work which was in the link, but I got the logical reason for the limitation of 1500 users. Thanks a ton for that. I found a workaround for the code. – Ashutosh Jun 29 '12 at 03:07
0

When there is the possibility that the result set that will be returned will contain more than 1000 items, you must use a paged search. Searches of Active Directory performed without paging are limited to returning a maximum of the first 1000 records. With a paged search, the result set is presented as individual pages, each containing a predetermined number of result entries. With this type of search, new pages of result entries are returned until the end of the result set is reached.

By default, the server that responds to a query request completely calculates a result set before returning data. In a large result set, this requires server memory as the result set is acquired, and network bandwidth when the large result is returned. Setting a page size allows the server to send the data in pages as the pages are being built. The client then caches this data and provides a cursor to the application level code.

Paging is set by defining how many rows the server calculates before the data is returned over the network to the client.

Jakub Konecki
  • 45,581
  • 7
  • 87
  • 126
0

Found the answer by researching through and trying my luck. Using Directory Entry was the problem, and did not ned to use Page Searching, although I tried the same.

The working code is as below:

GroupPrincipal grp = GroupPrincipal.FindByIdentity(pcRoot, adGroup); //fglbcmdolpctx
                if (grp != null)
                {
                    foreach (Principal p in grp.GetMembers(true))
                    {
                        try
                        {
                            dr = dt.NewRow();
                            dr["Application"] = "Commodities OpenLink";
                            dr["Profile"] = adGroupDesc;
                            string AccountName = p.SamAccountName.ToString().ToLower();
                            dr["Account Name"] = AccountName;
                            dr["Last Login"] = "";
                            string sLastName, sFirstName;
                            int iLastNameIndex0, iLastNameIndex1, iFirstNameIndex0, iFirstNameIndex1;
                            int lengthofString = p.Name.ToString().Length;
                            iLastNameIndex1 = p.Name.ToString().IndexOf(",");


                            if (iLastNameIndex1 == -1)
                            {
                                sLastName = "";
                            }
                            else
                            {
                                sLastName = p.Name.ToString().Substring(0, iLastNameIndex1);
                            }

                            iFirstNameIndex0 = p.Name.ToString().IndexOf(",");
                            iFirstNameIndex1 = p.Name.ToString().IndexOf(":");
                            if (iFirstNameIndex0 == -1 || iFirstNameIndex1 == -1)
                            {
                                sFirstName = p.Name.ToString();
                                sLastName = "";
                            }
                            else
                            {
                                sFirstName = p.Name.ToString().Substring(iFirstNameIndex0 + 1, iFirstNameIndex1 - iFirstNameIndex0 - 1);
                            }

                            sAccount_owner = sLastName + @"-" + sFirstName;
                            dr["Account Owner"] = sAccount_owner;

                            string sPath_Domain_Part;
                            string sFirstIndexofExtraction = "DC=";
                            int ilength_String = p.DistinguishedName.ToString().Length;
                            int iLenght_ExtractionPoint1 = p.DistinguishedName.ToString().IndexOf(sFirstIndexofExtraction);
                            string str1 = p.DistinguishedName.ToString().Substring(iLenght_ExtractionPoint1, ilength_String - iLenght_ExtractionPoint1);

                            string subStringE2 = ",DC";
                            int iLenght_ExtractionPoint2 = str1.IndexOf(subStringE2);
                            sPath_Domain_Part = str1.Substring(3, iLenght_ExtractionPoint2 - 3);
                            string sPath1 = sPath_Domain_Part + @"\" + adGroup + @"\" + p.SamAccountName.ToString();
                            dr["Path"] = sPath_Domain_Part + @"\" + adGroup + @"\" + p.SamAccountName.ToString();
                            dt.Rows.Add(dr);
                        }

                        catch (Exception ex)
                        {
                            Global.logfile.WriteLine("Error occured for user name" + adGroup + p.SamAccountName + "\n" + ex.Message);
                        }
                    }
                }
Ashutosh
  • 25
  • 1
  • 12