2012-03-02 9 views
18

He utilizado con éxito el código AccountManagement para recuperar información básica de AD, pero solo está devolviendo un conjunto muy limitado de información sobre el objeto devuelto. ¿Cómo puedo obtener información extendida de AD usando la funcionalidad AccountManagement? Específicamente, el título o título del trabajo, ya que parece ser llamado en mi instancia de AD.Obtener título de trabajo utilizando System.DirectoryServices.AccountManagement

Sé cómo hacerlo usando los viejos DirectoryServices, pero me gustaría saber cómo hacerlo utilizando el nuevo espacio de nombres.

Respuesta

32

Sí, el conjunto predeterminado de propiedades en UserPrincipal es bastante limitado, pero la gran parte es: ¡existe una prolija historia de extensibilidad en su lugar!

Debe definir una clase que descienda de UserPrincipal y luego podrá acceder fácilmente a muchas más propiedades, si es necesario.

El esqueleto sería algo como esto:

namespace ADExtended 
{ 
    [DirectoryRdnPrefix("CN")] 
    [DirectoryObjectClass("User")] 
    public class UserPrincipalEx : UserPrincipal 
    { 
     // Inplement the constructor using the base class constructor. 
     public UserPrincipalEx(PrincipalContext context) : base(context) 
     { } 

     // Implement the constructor with initialization parameters.  
     public UserPrincipalEx(PrincipalContext context, 
          string samAccountName, 
          string password, 
          bool enabled) : base(context, samAccountName, password, enabled) 
     {} 

     UserPrincipalExSearchFilter searchFilter; 

     new public UserPrincipalExSearchFilter AdvancedSearchFilter 
     { 
      get 
      { 
       if (null == searchFilter) 
        searchFilter = new UserPrincipalExSearchFilter(this); 

       return searchFilter; 
      } 
     } 

     // Create the "Title" property.  
     [DirectoryProperty("title")] 
     public string Title 
     { 
      get 
      { 
       if (ExtensionGet("title").Length != 1) 
        return string.Empty; 

       return (string)ExtensionGet("title")[0]; 
      } 
      set { ExtensionSet("title", value); } 
     } 

     // Implement the overloaded search method FindByIdentity. 
     public static new UserPrincipalEx FindByIdentity(PrincipalContext context, string identityValue) 
     { 
      return (UserPrincipalEx)FindByIdentityWithType(context, typeof(UserPrincipalEx), identityValue); 
     } 

     // Implement the overloaded search method FindByIdentity. 
     public static new UserPrincipalEx FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue) 
     { 
      return (UserPrincipalEx)FindByIdentityWithType(context, typeof(UserPrincipalEx), identityType, identityValue); 
     } 
    } 
} 

Y eso es realmente casi todo lo que hay! Los métodos y ExtensionGetExtensionSet le permiten "llegar a abajo" en la entrada de directorio subyacente y agarrar todos los atributos que le pueden interesar ....

Ahora, en su código, utiliza su nueva clase UserPrincipalEx en lugar de UserPrincipal :

using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain)) 
{ 
    // Search the directory for the new object. 
    UserPrincipalEx myUser = UserPrincipalEx.FindByIdentity(ctx, "someUserName"); 

    if(myUser != null) 
    { 
     // get the title which is now available on your "myUser" object! 
     string title = myUser.Title; 
    } 
} 

Lea todo sobre el espacio de nombres System.DirectoryServices.AccountManagement y su historia extensibilidad aquí:

Actualización: lo siento - aquí está la clase UserPrincipalExSearchFilter - se perdió esa en la publicación original. Esto demuestra la capacidad de extender también los filtros de búsqueda, si es necesario:

public class UserPrincipalExSearchFilter : AdvancedFilters 
{ 
    public UserPrincipalExSearchFilter(Principal p) : base(p) { } 

    public void LogonCount(int value, MatchType mt) 
    { 
     this.AdvancedFilterSet("LogonCount", value, typeof(int), mt); 
    } 
} 
+0

dónde viene este tipo (UserPrincipalExSearchFilter) viene? ¿Necesito crear este tipo usando el patrón de arriba? De hecho saqué esas pocas líneas de código y parece funcionar perfectamente (a menos que me falta algo). – Jay

+0

@Jay: lo siento, mi mal, olvidé incluir esto. Actualizado mi respuesta. –

+0

@ marc_s. Gracias por señalar el punto de extensibilidad (los métodos protegidos ExtensionGet/Set), creo que vale la pena mirar más de cerca a casa a veces !!) De todos modos, ¿conoce los problemas de seguridad/config necesarios para usar el objeto prinicpal derivado? He utilizado la subclase anterior y obtengo una excepción que dice "Los objetos principales de tipo UserPrincpalEx no se pueden usar para consultar esta tienda". ¿Algunas ideas? Gracias. – brumScouse

7

para aumentar la anterior He llamado a un método de extensión para llamar ExtensionGet. Utiliza la reflexión para obtener el método protegido que de otro modo tendrías que heredar. Es posible que necesite usar esta opción si va a devolver UserPrincipalObjects de Groups.Members, por ejemplo

public static class AccountManagmentExtensions 
{ 
    public static string ExtensionGet(this UserPrincipal up, string key) 
    { 
     string value = null; 
     MethodInfo mi = up.GetType() 
      .GetMethod("ExtensionGet", BindingFlags.NonPublic | BindingFlags.Instance); 

     Func<UserPrincipal, string, object[]> extensionGet = (k,v) => 
      ((object[])mi.Invoke(k, new object[] { v })); 

     if (extensionGet(up,key).Length > 0) 
     { 
      value = (string)extensionGet(up, key)[0]; 
     } 

     return value; 
    } 
} 
+0

+1 es un truco bastante útil. yo estaba como "¡oh, ahora necesito una subclase!" Simplemente está repasando el hecho de que el método está protegido y diseñado para acceder a él a través de una subclase. Me recuerda un tema que escribí sobre cómo puedes usar la reflexión .NET para "violar" los conceptos de OOP: http://mazdev.blogspot.ae/2011/05/breaching-object-oriented-programming.html – Mzn

+0

¿Cuál es el valor? de la clave no es un valor de cadena. como 'System._comObject' en la propiedad' accountExpires'. –

Cuestiones relacionadas