2012-05-15 10 views
23

Ist es möglich, System.DirectoryServices.AccountManagement.PrincipalSearcher zu verwenden, um basierend auf mehreren Parametern mit "oder" (nicht "und") zu suchen.Verwenden von PrincipalSearcher zum Suchen von Benutzern mit "oder" -Parametern

dh

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

und ich würde eine Suche ähnlich wie diese (in LDAP) gerne mit PrincipalSearcher (nicht DirectorySearcher)

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

Antwort

-4

Die FindAll Methode durchsucht die Domäne in der Haupt angegeben Kontext für Objekte mit identischen Eigenschaften wie im Abfragefilter . Die FindAll-Methode gibt alle Objekte zurück, die dem übergebenen Objekt entsprechen, während die FindOne-Methode nur ein einzelnes übereinstimmendes Prinzipalobjekt zurückgibt. http://msdn.microsoft.com/en-us/library/bb384378(v=vs.90).aspx

Ich weiß nicht, was Sie brauchen, aber man konnte eine Suche nach 1 proprety und 1 durch andere und dann mit LINQ auf den Listen tun fusionieren, Filter und etc ...

+0

Ja, das ist die Abhilfe, die ich bin derzeit mit, ich war es die Hoffnung sein, würde Möglichkeit, dies in einer Suche sauberer zu machen. Trotzdem danke. – doobist

13

es ist abviously nicht möglich, hier ist ein workarround:

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

Sie müssen damit umgehen Duplikate. Wenn der Anzeigename, der Vorname und der Kontoname alle den Namen "tom" enthalten, haben Sie Dubletten. –

+0

Ich wollte das auch, obwohl es bei mehreren Abfragen deutlich weniger performant ist? Ich frage mich, warum ich nicht einfach auf den DirectorySearcher zurückgreifen sollte, wenn das mit PrincipalSearcher nicht möglich ist – PandaWood

4

nicht unbedingt so sauber, wie einige der anderen Antworten, aber hier ist, wie ich dies in einem Projekt umgesetzt habe ich arbeite. Ich wollte, dass beide Suchvorgänge async ausgeführt werden, um zu versuchen, Verzögerungen aufgrund von zwei AD-Abfragen zu reduzieren.

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

Meine ADUserEntity-Klasse hat eine Gleichheitsprüfung basierend auf der SID. Ich habe versucht, die Distinct() auf die Union() der beiden Sucher Ergebnisse hinzuzufügen, aber das hat nicht funktioniert.

Ich begrüße jede konstruktive Kritik an meiner Antwort, da ich gerne wissen würde, ob es irgendeinen Weg gibt, wie ich es verbessern kann.

+1

Um nur einzelne zurückgegebene Benutzer zu erhalten, können Sie LINQ verwenden, um nach einem Bezeichner (zB SID) zu gruppieren: Ersetzen 'return users.Distinct() .ToList(); 'mit' return users.GroupBy (user => user.Sid) .Wählen Sie (group => group.First()). ToList(); ' –

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

Ich weiß, diese Art von spät ist, aber das ist das Konstrukt ich beim AD Suche:

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; 
    }); 
} 
+0

Sie lesen grundsätzlich das gesamte Verzeichnis und Durchführen der Filterung im Client. Dies kann nicht für ein mittelgroßes Verzeichnis und größer skaliert werden. –

+0

Ich habe seitdem vor dem Ausführen der Suche das UserPrincipal-Objekt gefiltert und den Bereich der Suche auf eine bestimmte Start-OU eingegrenzt. –

Verwandte Themen