使用PrincipalSearcher查找具有“或”参数的用户

是否可以使用System.DirectoryServices.AccountManagement.PrincipalSearcher使用“或”(不是“和”)基于多个参数进行搜索。

 // 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(); 

我希望使用PrincipalSearcher (而不是DirectorySearcher )进行类似的搜索(在LDAP中)

 // (&(objectCategory=person)(!UserAccountControl:1.2.840.113556.1.4.803:=2)(|(SAMAccountName=tom*)(DisplayName=tom*))) 

这显然是不可能的,这是一个解决方法:

 List searchPrinciples = new List(); 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 results = new List(); var searcher = new PrincipalSearcher(); foreach (var item in searchPrinciples) { searcher = new PrincipalSearcher(item); results.AddRange(searcher.FindAll()); } 

不一定像其他一些答案一样干净,但这里是我在我正在研究的项目中实现这一点的方式。 我希望两个搜索都运行异步,以尝试减少由于运行两个AD查询导致的任何减速。

 public async static Task> FindUsers(String searchString) { searchString = String.Format("*{0}*", searchString); List users = new List(); 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> taskDisplayname = Task.Run>(() => searcherDisplayname.FindAll())) using (Task> taskUsername = Task.Run>(() => searcherUsername.FindAll())) { foreach (UserPrincipal userPrincipal in (await taskDisplayname).Union(await taskUsername)) using (userPrincipal) { users.Add(new ADUserEntity(userPrincipal)); } } return users.Distinct().ToList(); } 

我的ADUserEntity类具有基于SID的相等性检查。 我试图将Distinct()添加到两个搜索者结果的Union()上但是没有用。

我欢迎对我的答案进行任何建设性的批评,因为我想知道是否有任何方法可以改进它。

我知道这有点晚了,但这是我在搜索AD时使用的构造:

 public static Task> GetUsers(//Whatever filters you want) { return Task.Run(() => { PrincipalContext context = new PrincipalContext(ContextType.Domain); UserPrincipal principal = new UserPrincipal(context); principal.Enabled = true; PrincipalSearcher searcher = new PrincipalSearcher(principal); var users = searcher.FindAll().Cast() .Where(x => x.SomeProperty... // Perform queries) .Select(x => new SomeUserModelClass { userName = x.SamAccountName, email = x.UserPrincipalName, guid = x.Guid.Value }).OrderBy(x => x.userName).AsEnumerable(); return users; }); } 

FindAll方法在主体上下文中指定的域中搜索具有与查询filter上设置的属性相同的属性的对象 。 FindAll方法返回与提供的对象匹配的所有对象,而FindOne方法仅返回单个匹配的主体对象。 http://msdn.microsoft.com/en-us/library/bb384378(v=vs.90).aspx

我不知道你需要什么,但你可以通过1 proprety和1 by other进行搜索,然后在列表上使用LINQ进行合并,过滤等…

 PrincipalContext pContext = new PrincipalContext(ContextType.Machine, Environment.MachineName); GroupPrincipal gp = GroupPrincipal.FindByIdentity(pContext, "Administrators"); bool isMember = UserPrincipal.Current.IsMemberOf(gp);