user222427
user222427

Reputation:

Why does my DirectorySearcher throw an ArgumentOutOfRangeException when I try to retrieve a property by name?

I have over 1500 users in a specific AD group, and when I pull them down I'm limited as to who I get. I saw this article on MSDN (http://msdn.microsoft.com/en-us/library/ms180907%28v=vs.80%29.aspx) however it performs a FindOne(); doing this takes the app over 10 minutes to pull down the users. With a SearchResultsCollection and .FindAll(), I'm able to pull down all the users in 30 seconds.

However, when it goes to process

string Last_Name = userResults.Properties["sn"][0].ToString();

it comes back with the error:

Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index

I figured this had the problem of not finding the results however, the SearchResultsCollection contains all 1000 entries.

As a note: The surname is not empty for these users, the issue is resultCollection is only returning 1 property and that's adpath

DirectoryEntry dEntryhighlevel = new DirectoryEntry("LDAP://OU=Clients,OU=x,DC=h,DC=nt");

DirectorySearcher dSeacher = new DirectorySearcher(dEntryhighlevel);
dSeacher.Filter = "(&(objectClass=user)(memberof=CN=Users,,OU=Clients,OU=x,DC=h,DC=nt))";

uint rangeStep = 1000;
uint rangeLow = 1;
uint rangeHigh = rangeLow + (rangeStep -1);
bool lastQuery = false;
bool quitLoop = false;
            
do
{
    string attributeWithRange;

    if (!lastQuery)
    {
        attributeWithRange = String.Format("member;range={0}-{1}", rangeLow, rangeHigh);
    }
    else
    {
        attributeWithRange = String.Format("member;range={0}-*", rangeLow);
    }

    dSeacher.PropertiesToLoad.Clear();
    dSeacher.PropertiesToLoad.Add(attributeWithRange);

    SearchResultCollection resultCollection = dSeacher.FindAll();

    foreach (SearchResult userResults in resultCollection)
    {
        string Last_Name = userResults.Properties["sn"][0].ToString();
        string First_Name = userResults.Properties["givenname"][0].ToString();
        string userName = userResults.Properties["samAccountName"][0].ToString();
        string Email_Address = userResults.Properties["mail"][0].ToString();
        OriginalList.Add(Last_Name + "|" + First_Name + "|" + userName + "|" + Email_Address);

        if (userResults.Properties.Contains(attributeWithRange))
        {
            foreach (object obj in userResults.Properties[attributeWithRange])
            {
                Console.WriteLine(obj.GetType());

                if (obj.GetType().Equals(typeof(System.String)))
                {
                }
                else if (obj.GetType().Equals(typeof(System.Int32)))
                {
                }

                Console.WriteLine(obj.ToString());
            }

            if (lastQuery)
            {
                quitLoop = true;
            }
        }
        else
        {
           lastQuery = true;
        }

        if (!lastQuery)
        {
            rangeLow = rangeHigh + 1;
            rangeHigh = rangeLow + (rangeStep - 1);
        }
   }
}
while (!quitLoop);

Upvotes: 4

Views: 14107

Answers (2)

user222427
user222427

Reputation:

If you specify any properties with .PropertiesToLoad(), it will not load any other properties. As such you have to specify all properties you want to load. For example, to get givenname, sn, samAccountName and mail, you need to include:

dSeacher.PropertiesToLoad.Clear();
dSeacher.PropertiesToLoad.Add(attributeWithRange);
dSeacher.PropertiesToLoad.Add("givenname");
dSeacher.PropertiesToLoad.Add("sn");
dSeacher.PropertiesToLoad.Add("samAccountName");
dSeacher.PropertiesToLoad.Add("mail");

Upvotes: 3

Eric Fleischman
Eric Fleischman

Reputation: 1158

I wouldn't go down this path. It is easier (and less error prone) to read membership via a base search against the group than it is to do large subtree searches like this.

As you observed,when you try and read the member attribute on a large group, you'll only get 1500 values per read. The way to get all off the members of the group is via a capability typically called "ranged retrieval." I provided the link to info on this here: Always getting 1500 member of distribution list using PowerShell

Upvotes: 1

Related Questions