Can I get more than 1000 records from a DirectorySearcher?
You need to set DirectorySearcher.PageSize to a non-zero value to get all results.
BTW you should also dispose DirectorySearcher when you're finished with it
using(var srch = new DirectorySearcher(dirEnt, "(objectClass=Group)", loadProps))
{
srch.PageSize = 1000;
var results = srch.FindAll();
}
The API documentation isn't very clear, but essentially:
when you do a paged search, the SizeLimit is ignored, and all matching results are returned as you iterate through the results returned by FindAll. Results will be retrieved from the server a page at a time. I chose the value of 1000 above, but you can use a smaller value if preferred. The tradeoff is: using a small PageSize will return each page of results faster, but will require more frequent calls to the server when iterating over a large number of results.
by default the search isn't paged (PageSize = 0). In this case up to SizeLimit results is returned.
As Biri pointed out, it's important to dispose the SearchResultCollection returned by FindAll, otherwise you may have a memory leak as described in the Remarks section of the MSDN documentation for DirectorySearcher.FindAll.
One way to help avoid this in .NET 2.0 or later is to write a wrapper method that automatically disposes the SearchResultCollection. This might look something like the following (or could be an extension method in .NET 3.5):
public IEnumerable<SearchResult> SafeFindAll(DirectorySearcher searcher)
{
using(SearchResultCollection results = searcher.FindAll())
{
foreach (SearchResult result in results)
{
yield return result;
}
} // SearchResultCollection will be disposed here
}
You could then use this as follows:
using(var srch = new DirectorySearcher(dirEnt, "(objectClass=Group)", loadProps))
{
srch.PageSize = 1000;
var results = SafeFindAll(srch);
}
c# Active Directory Services findAll() returns only 1000 entries
This is due to a server-side limit. From the DirectorySearcher.SizeLimit
documentation:
The maximum number of objects that the
server returns in a search. The
default value is zero, which means to
use the server-determined default size
limit of 1000 entries.
And:
If you set SizeLimit to a value that is larger than the server-determined default of 1000
entries, the server-determined default is used.
Basically from this, it looks like unless there's a way of changing the server-side default, you're going to be limited to 1000 entries. It's possible that specifying a PageSize
will let you fetch a certain number at a time, with a total greater than 1000... not sure.
By the way, it looks like you should also have a using
directive around the SearchResultCollection
:
using (SearchResultCollection results = ds.FindAll())
{
foreach (SearchResult sr in results)
{
...
}
}
Can I get more than 1000 records from a PrincipalSearcher?
I don't think you will be able to do that without using DirectorySearcher.
Code snippet -
// set the PageSize on the underlying DirectorySearcher to get all entries
((DirectorySearcher)search.GetUnderlyingSearcher()).PageSize = 1000;
Also see If an OU contains 3000 users, how to use DirectorySearcher to find all of them?
If an OU contains 3000 users, how to use DirectorySearcher to find all of them?
If you're on .NET 3.5 or newer, you should check out the PrincipalSearcher
and a "query-by-example" principal to do your searching:
// create your domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "YOURDOMAIN", "OU=SomeOU,DC=YourCompany,DC=com");
// define a "query-by-example" principal - here, we search for a UserPrincipal
// and with the first name (GivenName) of "Bruce"
UserPrincipal qbeUser = new UserPrincipal(ctx);
qbeUser.GivenName = "Bruce";
// create your principal searcher passing in the QBE principal
PrincipalSearcher srch = new PrincipalSearcher(qbeUser);
// set the PageSize on the underlying DirectorySearcher to get all 3000 entries
((DirectorySearcher)srch.GetUnderlyingSearcher()).PageSize = 500;
// find all matches
foreach(var found in srch.FindAll())
{
// do whatever here - "found" is of type "Principal" - it could be user, group, computer.....
}
If you haven't already - absolutely read the MSDN article Managing Directory Security Principals in the .NET Framework 3.5 which shows nicely how to make the best use of the new features in System.DirectoryServices.AccountManagement
Update:
Of course, depending on your need, you might want to specify other properties on that "query-by-example" user principal you create:
Surname
(or last name)DisplayName
(typically: first name + space + last name)SAM Account Name
- your Windows/AD account nameUser Principal Name
- your "username@yourcompany.com" style name
You can specify any of the properties on the UserPrincipal
and use those as "query-by-example" for your PrincipalSearcher
.
Update #2: If you want to search just inside a given OU, you can define that OU in the constructor of the PrincipalContext
.
Get total number of search results for paginated DirectorySearcher
There is an ApproximateTotal
property inside DirectoryVirtualListView
class. You can use it, but remember you should access it after the foreach
block in your code.
Just change this line:
Console.WriteLine("Found: " + results.Count);
to this one:
Console.WriteLine("Found: " + searcher.VirtualListView.ApproximateTotal);
All done!
Related Topics
How to Get Client Date and Time in ASP.NET
Enabling C# 7 in a ASP.NET Application
Datagridview Bound to a Dictionary
Sqlite Database Locked Exception
Transparent Images with C# Winforms
How to Deserialize a Complex JSON Object in C# .Net
C# Using Parameters.Addwithvalue in SQLdataadapter
Adding Parameters in SQLite with C#
Custom Collection Initializers
Thread.Sleep for Less Than 1 Millisecond
How to Filter "Include" Entities in Entity Framework
Setting the User-Agent Header for a Webclient Request
Most Elegant Xml Serialization of Color Structure
Find a Control in Windows Forms by Name