Is it possible to use System.DirectoryServices.AccountManagement.PrincipalSearcher
to search based on multiple parameters using "or" (not "and").
i.e.
// This uses an and
//(&(objectCategory=person)(!UserAccountControl:1.2.840.113556.1.4.803:=2)(&(SAMAccountName=tom*)(DisplayName=tom*)))
var searchPrinciple = new UserPrincipal(context);
searchPrinciple.DisplayName = "tom*";
searchPrinciple.SamAccountName = "tom*";
var searcher = new PrincipalSearcher();
searcher.QueryFilter = searchPrinciple;
var results = searcher.FindAll();
and I would like a search similar to this (in LDAP) using PrincipalSearcher
(not DirectorySearcher
)
// (&(objectCategory=person)(!UserAccountControl:1.2.840.113556.1.4.803:=2)(|(SAMAccountName=tom*)(DisplayName=tom*)))
It's obviously not possible, here is a workaround:
List<UserPrincipal> searchPrinciples = new List<UserPrincipal>();
searchPrinciples.Add(new UserPrincipal(context) { DisplayName="tom*"});
searchPrinciples.Add(new UserPrincipal(context) { SamAccountName = "tom*" });
searchPrinciples.Add(new UserPrincipal(context) { MiddleName = "tom*" });
searchPrinciples.Add(new UserPrincipal(context) { GivenName = "tom*" });
List<Principal> results = new List<Principal>();
var searcher = new PrincipalSearcher();
foreach (var item in searchPrinciples)
{
searcher = new PrincipalSearcher(item);
results.AddRange(searcher.FindAll());
}
Not necessarily as clean as some of the other answers but here is how I've implemented this in a project I'm working on. I wanted both searches to be run async to try and reduce any slow down due to running two AD queries.
public async static Task<List<ADUserEntity>> FindUsers(String searchString)
{
searchString = String.Format("*{0}*", searchString);
List<ADUserEntity> users = new List<ADUserEntity>();
using (UserPrincipal searchMaskDisplayname = new UserPrincipal(domainContext) { DisplayName = searchString })
using (UserPrincipal searchMaskUsername = new UserPrincipal(domainContext) { SamAccountName = searchString })
using (PrincipalSearcher searcherDisplayname = new PrincipalSearcher(searchMaskDisplayname))
using (PrincipalSearcher searcherUsername = new PrincipalSearcher(searchMaskUsername))
using (Task<PrincipalSearchResult<Principal>> taskDisplayname = Task.Run<PrincipalSearchResult<Principal>>(() => searcherDisplayname.FindAll()))
using (Task<PrincipalSearchResult<Principal>> taskUsername = Task.Run<PrincipalSearchResult<Principal>>(() => searcherUsername.FindAll()))
{
foreach (UserPrincipal userPrincipal in (await taskDisplayname).Union(await taskUsername))
using (userPrincipal)
{
users.Add(new ADUserEntity(userPrincipal));
}
}
return users.Distinct().ToList();
}
My ADUserEntity class has an equality check based on the SID. I tried to add the Distinct()
on to the Union()
of the two searcher results but that didn't work.
I welcome any constructive criticism on my answer as I'd like to know if there is any way I can improve it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With