Reputation:
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
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
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