2012-02-28 10 views
6

I'am de vuelta con mi herramienta de Active Directory ...Obtener una lista de grupos de miembros (memberOf) en Active Directory

I'am tratar de enumerar los grupos en el "miembro de" atributo de un usuario. A continuación se muestra la función que utilizo:

public static DataTable ListGroupsByUser(string selectedOu) 
{ 
    DataTable groupListByUser = new DataTable(); 
    String dom = "OU=" + selectedOu + ",OU=XXX,DC=XXX,DCXXX,DC=XXX,DC=XXX"; 
    DirectoryEntry directoryObject = new DirectoryEntry("LDAP://" + dom); 

    DataColumn column; 
    DataRow row; 

    column = new DataColumn(); 
    column.ColumnName = "ID"; 
    groupListByUser.Columns.Add(column); 

    column = new DataColumn(); 
    column.ColumnName = "User"; 
    groupListByUser.Columns.Add(column); 

    column = new DataColumn(); 
    column.ColumnName = "Groups"; 
    groupListByUser.Columns.Add(column); 
    int i = 1; 

    foreach (DirectoryEntry child in directoryObject.Children) 
    {     
     row = groupListByUser.NewRow(); 
     groupListByUser.Rows.Add(row); 
     row["ID"] = i++; 

     if (child.Properties["memberOf"].Value != null) 
     {      
      row["User"] = child.Properties["sAMAccountName"].Value.ToString(); 
      row["Groups"] = child.Properties["memberOf"].Value.ToString(); 
     } 
     else 
     { 
      row["Groups"] = "blabla"; 
     } 
    } 
    return groupListByUser; 
} 

Devuelve el grupo adecuado para los usuarios que pertenecen a un solo grupo. Tan pronto como Hay más de un grupo, devuelve System.Object [].

¿Cómo puedo hacer para ver todos los grupos?

Respuesta

4

Si tiene .NET 3.5 y superior, debe verificar el espacio de nombres System.DirectoryServices.AccountManagement (S.DS.AM). Leer todos los detalles aquí:

Básicamente, se puede definir un contexto de dominio y encontrar fácilmente los usuarios y/o grupos en el año:

// set up domain context 
PrincipalContext ctx = new PrincipalContext(ContextType.Domain); 

// find a user 
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "SomeUserName"); 

if(user != null) 
{ 
    var groups = user.GetGroups(); 
    // or there's also: 
    //var authGroups = userByEmail.GetAuthorizationGroups() 
} 

El llama al GetGroups() o GetAuthorizationGroups() devolverá la membresía anidada del grupo, también - entonces ¡ya no es necesario que caces esas membresías anidadas!

¡El nuevo S.DS.AM hace que sea realmente fácil jugar con usuarios y grupos en AD!

+0

Gracias Marc, me las arreglé para tratar con usuarios y grupos, lo que no puedo hacer es recorrer la lista de membresías de los usuarios. ¿Merece la pena reconstruir la herramienta con el espacio de nombres accountManagement en lugar de directoryServices? –

+0

@Oliver: Gracias chicos. A pesar de sus consejos, encontré una solución, siguiendo: 'code' if (child.Properties ["memberOf"]. Value! = Null) { foreach (Object memberof en child.Properties ["memberOf"]) { // row ["User"] = child.Properties ["sAMAccountName"]. Value.ToString(); row ["Member Of"] + = memberof.ToString() + "///"; } } else { row ["Member Of"] = "Sin grupo definido"; } –

4

El problema es su Properties["memberOf"].Value.ToString().

Hice un poco de investigación y este código trabajó para mí:

var memberGroups = child.Properties["memberOf"].Value; 

if (memberGroups.GetType() == typeof(string)) 
{ 
    row["Groups"] = (String)memberGroups; 
} 
else if (memberGroups.GetType().IsArray) 
{ 
    var memberGroupsEnumerable = memberGroups as IEnumerable; 

    if (memberGroupsEnumerable != null) 
    { 
     var asStringEnumerable = memberGroupsEnumerable.OfType<object>().Select(obj => obj.ToString()); 
     row["Groups"] = String.Join(", ", asStringEnumerable); 
    } 
} 
else 
{ 
    row["Groups"] = "No group found."; 
} 

No es muy lindo pero funciona y da espacio para mejoras adicionales. ;-)

+0

Gracias Oliver, probé tu solución pero parece un poco complicado. Realmente no entiendo lo que estoy haciendo con esto: var groups = objArray.Cast (). Select (elem => elem.Values.ToString()); Me devuelve un error: el valor no puede ser nulo. Nombre del parámetro: fuente –

+0

@HenryMeyer: he trabajado de nuevo en mi código, pero creo que el enfoque de marc_s es realmente mejor a largo plazo, porque no tiene que molestarse con este conjunto de cadenas y matrices de objetos. Son clases específicas del tipo que hacen que sea más fácil acceder a todo esto mucho más conveniente. – Oliver

Cuestiones relacionadas