2010-11-26 45 views
12

Estoy usando la parte System.DirectoryServices.AccountManagement de la biblioteca .Net para interactuar con ActiveDirectory.Obtiene nETBIOSName de un objeto UserPrincipal

haber emplazado GetMembers() en un objeto GroupPrincipal y filtrar los resultados, ahora tengo una colección de objetos UserPrincipal

GroupPrincipal myGroup; // population of this object omitted here 

foreach (UserPrincipal user in myGroup.GetMembers(false).OfType<UserPrincipal>()) 
{ 
    Console.WriteLine(user.SamAccountName); 
} 

El ejemplo de código anterior se imprimirá nombres de usuario como "TestUser1". Necesito compararlos con una lista proveniente de otra aplicación en el formato "DOMAIN \ TestUser1".

¿Cómo obtengo la parte "DOMAIN" del objeto UserPrincipal?

No puedo agregar simplemente un nombre de dominio conocido ya que hay varios dominios implicados y necesito diferenciar DOMAIN1 \ TestUser1 y DOMAIN2 \ TestUser2.

+0

@marc_s El nombrePrincipalUsuario contiene el nombre en formato [email protected] - No veo cómo convertirlo fácilmente en el formato DOMINIO \ usuario (especialmente porque los dominios implicados son una lista conocida - cada entorno de producción será una lista diferente de dominios que mi entorno dev) – Grhm

+0

También puede usar 'msDS -PrincipalName' propiedad como se describe aquí http://stackoverflow.com/questions/10702188/ –

+2

O use 'user.Sid.Translate (typeof (System.Security.Principal.NTAccount)). ToString()' para obtener el dominio \ Nombre de usuario de eac h miembro del grupo. Consulte http://stackoverflow.com/questions/6759463 –

Respuesta

4

Tiene dos opciones que se me ocurren.

  1. Analizar, o tomar todo lo que está en adelante, el derecho de [email protected];
  2. Use el espacio de nombres System.DirectoryServices.

No sé sobre UserPrincipal, ni hacer sobre GroupPrincipal. Por otro lado, sé de una forma efectiva de lograr lo que quieres.

[TestCase("LDAP://fully.qualified.domain.name", "TestUser1")] 
public void GetNetBiosName(string ldapUrl, string login) 
    string netBiosName = null; 
    string foundLogin = null; 

    using (DirectoryEntry root = new DirectoryEntry(ldapUrl)) 
     Using (DirectorySearcher searcher = new DirectorySearcher(root) { 
      searcher.SearchScope = SearchScope.Subtree; 
      searcher.PropertiesToLoad.Add("sAMAccountName"); 
      searcher.Filter = string.Format("(&(objectClass=user)(sAMAccountName={0}))", login); 

      SearchResult result = null; 

      try { 
       result = searcher.FindOne(); 

       if (result == null) 
        if (string.Equals(login, result.GetDirectoryEntry().Properties("sAMAccountName").Value)) 
         foundLogin = result.GetDirectoryEntry().Properties("sAMAccountName").Value 
      } finally { 
       searcher.Dispose(); 
       root.Dispose(); 
       if (result != null) result = null; 
      } 
     } 

    if (!string.IsNullOrEmpty(foundLogin)) 
     using (DirectoryEntry root = new DirectoryEntry(ldapUrl.Insert(7, "CN=Partitions,CN=Configuration,DC=").Replace(".", ",DC=")) 
      Using DirectorySearcher searcher = new DirectorySearcher(root) 
       searcher.Filter = "nETBIOSName=*"; 
       searcher.PropertiesToLoad.Add("cn"); 

       SearchResultCollection results = null; 

       try { 
        results = searcher.FindAll(); 

        if (results != null && results.Count > 0 && results[0] != null) { 
         ResultPropertyValueCollection values = results[0].Properties("cn"); 
         netBiosName = rpvc[0].ToString(); 
       } finally { 
        searcher.Dispose(); 
        root.Dispose(); 

        if (results != null) { 
         results.Dispose(); 
         results = null; 
        } 
       } 
      } 

    Assert.AreEqual("INTRA\TESTUSER1", string.Concat(netBiosName, "\", foundLogin).ToUpperInvariant()) 
} 

Otra información relacionada o enlaces disponibles en esta pregunta.
C# Active Directory: Get domain name of user?
How to find the NetBIOS name of a domain

+0

Se ve bien pero no funciona. El resultado. GetDirectoryEntry() no tiene una propiedad "nETBIOSName"; siempre es nulo. (Además, tuve que usar Properties ["nETBIOSName"]. Value y mi objeto resultante no tiene un Dispose() - usando .Net4 si eso hace la diferencia) – Grhm

+0

@Grmh: Edité mi respuesta. Por favor, eche un vistazo y dígame si funciona. Lo he encapsulado dentro de NUnit TestCase para facilitar las pruebas. –

+0

@Will: no parece tener un "CN = Particiones, CN = Configuración" en mi dominio. Mi dominio aparentemente es un dominio secundario y el padre tiene una sección CN = Copnfiguration. Tendré que investigar ... – Grhm

0

¿Ha intentado pasar el nombre de dominio completo a esta otra aplicación? La mayoría de las API de Windows no se quejarán si lo hace fully_qualified_domain\USER.

+0

Desafortunadamente, la otra aplicación almacena los nombres de usuario en una base de datos y espera que el nombre de usuario sea único . También se conecta con otras aplicaciones a las que no tengo acceso. – Grhm

2

Uso de la biblioteca Activeds COM, se ha incorporado en la traducción de nombres que funciona y no hace ninguna suposición (al igual que otras respuestas aquí).

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using ActiveDs; 

namespace Foo.Repository.AdUserProfile 
{ 
    public class ADUserProfileValueTranslate 
    { 
     public static string ConvertUserPrincipalNameToNetBiosName(string userPrincipleName) 
     { 
      NameTranslate nameTranslate = new NameTranslate(); 
      nameTranslate.Set((int)ADS_NAME_TYPE_ENUM.ADS_NAME_TYPE_USER_PRINCIPAL_NAME, userPrincipleName); 
      return nameTranslate.Get((int) ADS_NAME_TYPE_ENUM.ADS_NAME_TYPE_NT4); 
     } 
    } 
} 
0

Puede buscar los posibles dominios en la propiedad user.DistinguishedName. Un usuario en el Dominio 1 debe contener la cadena "DC = DOMAIN1". Definitivamente no debería contener la cadena "DC = DOMAIN2".

+1

No necesariamente. Tenía un dominio que era [email protected] o PROJECTDEV \ User1 El user.DistinguishedName terminó con DC = dev, DC = proyecto, DC = local no contiene DC = PROJECTDEV – Grhm

+0

Ah - thx para la corrección. Creía que el nombre distinguido era en cierto sentido un campo calculado, y es consistente en mi entorno. –

0

Como se mencionó en uno de los comentarios a la pregunta creo que esto es una buena respuesta para tiempos más recientes:

user.Sid.Translate(typeof(System.Security.Principal.NTAccount)).ToString() 
Cuestiones relacionadas