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

时间:2012-05-15 18:02:38

标签: c# .net active-directory

是否可以使用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*)))

5 个答案:

答案 0 :(得分:18)

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

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

答案 1 :(得分:5)

不一定像其他一些答案一样干净,但这是我在我正在开展的项目中实现这一点的方式。我希望两个搜索都运行异步,以尝试减少由于运行两个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(),但这不起作用。

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

答案 2 :(得分:2)

我知道这有点晚了,但这是我在搜索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;
    });
}

答案 3 :(得分:-4)

  

FindAll方法搜索主体中指定的域   context 用于具有与on上设置的属性相同的属性的对象   查询过滤器。 FindAll方法返回匹配的所有对象   提供的对象,而FindOne方法只返回一个   匹配主要对象。   http://msdn.microsoft.com/en-us/library/bb384378(v=vs.90).aspx

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

答案 4 :(得分:-5)

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