2012-12-07 7 views
8

Sto cercando di cercare utenti in un'istanza di AD LDS (ADAM) in cui una proprietà non è impostata, ad esempio dove la proprietà "company" non è impostata su un valore nell'archivio ADAM (o AD per quella materia).Come trovare un UserPrincipal in cui una proprietà non viene impostata utilizzando PrincipalSearcher?

Quando uso una PrincipalSearcher e un costume UserPrincipal con un oggetto personalizzato AdvancedSearchFilters, ottengo l'errore:

An unhandled exception of type 'System.ArgumentException' occurred in System.DirectoryServices.dll 

Additional information: The (&(objectClass=user)(!(company=))) search filter is invalid. 

Ecco il mio codice di esempio:

using System; 
using System.DirectoryServices.AccountManagement; 
using System.Security.Permissions; 
using System.Linq; 

namespace AdamDump 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      PrincipalContext context = new PrincipalContext(ContextType.ApplicationDirectory, "MyAdamInstance:50000", "OU=Adam Users,dc=apps01,dc=mydomain", "queryaccount", "password");   

      // initialize a Query By Example 
      using (MyUserPrincipal myUserPrincipal = new MyUserPrincipal(context)) 
      { 
       myUserPrincipal.MyAdvancedFilters.WhereCompanyNotSet(); 

       PrincipalSearchResult<Principal> principals = null; 

       // do the search... 
       using (PrincipalSearcher principalSearcher = new PrincipalSearcher(myUserPrincipal)) 
       { 
        principals = principalSearcher.FindAll(); 
       } 

       var myUsers = principals.Select(principal => principal as MyUserPrincipal).ToList(); 

       foreach (var user in myUsers) 
        Console.WriteLine("Name: {0}, Account{1}", user.DisplayName, user.SamAccountName); 

       Console.WriteLine("Total found: {0}", myUsers.Count); 
      }     
     } 
    } 


    [DirectoryObjectClass("user")] 
    [DirectoryRdnPrefix("CN")] 
    [EnvironmentPermissionAttribute(SecurityAction.LinkDemand, Unrestricted = true)] 
    public class MyUserPrincipal : UserPrincipal 
    { 
     private MyAdvancedFilters _myAdvancedFilters; 

     /// <summary> 
     /// Initializes a new instance of the <see cref="MyUserPrincipal"/> class. 
     /// </summary> 
     /// <param name="context">A <see cref="PrincipalContext"/> to associate this instance with.</param> 
     [EnvironmentPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)] 
     public MyUserPrincipal(PrincipalContext context) 
      : base(context) { } 

     public MyAdvancedFilters MyAdvancedFilters 
     { 
      get 
      { 
       return this.AdvancedSearchFilter as MyAdvancedFilters; 
      } 
     } 

     public override AdvancedFilters AdvancedSearchFilter 
     { 
      get 
      { 
       if (_myAdvancedFilters == null) 
       { 
        _myAdvancedFilters = new MyAdvancedFilters(this);      
       } 

       return _myAdvancedFilters; 
      } 
     } 
    } 

    public class MyAdvancedFilters : AdvancedFilters 
    { 
     /// <summary> 
     /// Initializes a new instance of the <see cref="MyAdvancedFilters"/> class. 
     /// </summary> 
     /// <param name="principal">The source <see cref="Principal"/></param> 
     public MyAdvancedFilters(Principal principal) : base(principal) { } 

     public void WhereCompanyNotSet() 
     { 
      this.AdvancedFilterSet("company", "", typeof(string), MatchType.NotEquals); 
     } 
    } 
} 

risposta

8

Modificare la mia classe AdvanceFilters come segue ottiene i risultati che mi servono.

public class MyAdvancedFilters : AdvancedFilters 
{ 
    /// <summary> 
    /// Initializes a new instance of the <see cref="MyAdvancedFilters"/> class. 
    /// </summary> 
    /// <param name="principal">The source <see cref="Principal"/></param> 
    public MyAdvancedFilters(Principal principal) : base(principal) { } 

    public void WhereCompanyNotSet() 
    { 
     this.AdvancedFilterSet("company", "*", typeof(string), MatchType.NotEquals); 
    } 
} 

E 'il "*" per la parte di valore nel AdvancedFilterSet.

Grazie a Sean per aver portato sul sentiero giusto per trovare la risposta appropriata per gli oggetti AccountManagement.

3

Provare ad usare questa come query :

(&(objectClass=user)(!(company=*))) 

Documenti: http://msdn.microsoft.com/en-gb/library/windows/desktop/aa746475(v=vs.85).aspx a circa metà della pagina dice "Ottieni tutte le voci senza un attributo email:"

+0

Penso che tu abbia ragione per un approccio usando DirectorySearcher ma poiché ho bisogno di farlo tramite gli oggetti AccountManagement, questo non è direttamente applicabile. – Jim

+0

+1 per avermi messo sulla strada giusta però. – Jim

+0

Provalo con gli oggetti AccountManagement PrincipalSearcher ps = new PrincipalSearcher (utente); ((DirectorySearcher) ps.GetUnderlyingSearcher()). Filter = "(& (objectClass = utente) (! (Azienda = *)))"; / – hidden