Использование 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();
и мне нужен поиск, подобный этому (в LDAP) с помощью PrincipalSearcher
(not DirectorySearcher
)
// (&(objectCategory=person)(!UserAccountControl:1.2.840.113556.1.4.803:=2)(|(SAMAccountName=tom*)(DisplayName=tom*)))
Ответы
Ответ 1
Это, по-видимому, невозможно, вот рабочий стол:
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());
}
Ответ 2
Не обязательно такой же чистый, как некоторые другие ответы, но вот как я реализовал это в проекте, над которым я работаю. Я хотел, чтобы оба запроса выполнялись async, чтобы попытаться уменьшить замедление из-за запуска двух запросов AD.
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();
}
В моем классе ADUserEntity есть проверка равенства на основе SID. Я попытался добавить Distinct()
к Union()
из двух результатов поиска, но это не сработало.
Я приветствую конструктивную критику моего ответа, поскольку я хотел бы знать, есть ли способ улучшить его.
Ответ 3
Я знаю, что это немного поздно, но это конструкция, которую я использую при поиске AD:
public static Task<IEnumerable<SomeUserModelClass>> 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<UserPrincipal>()
.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;
});
}
Ответ 4
Метод FindAll ищет домен, указанный в принципе контекст для объектов, которые имеют одинаковые свойства с теми, которые установлены на фильтр запросов. Метод FindAll возвращает все объекты, соответствующие а метод FindOne возвращает только один сопоставление основного объекта. http://msdn.microsoft.com/en-us/library/bb384378(v=vs.90).aspx
Я не знаю, что вам нужно, но вы можете выполнить поиск по 1 proprety и 1 другим, а затем использовать LINQ в списках для слияния, фильтрации и т.д.
Ответ 5
PrincipalContext pContext = new PrincipalContext(ContextType.Machine, Environment.MachineName);
GroupPrincipal gp = GroupPrincipal.FindByIdentity(pContext, "Administrators");
bool isMember = UserPrincipal.Current.IsMemberOf(gp);