2009-12-07 4 views
4

J'utilise les classes d'espace de noms System.DirectoryServices.AccountManagement pour gérer l'appartenance de plusieurs groupes. Ces groupes contrôlent la population de notre système de comptabilité d'impression et certains d'entre eux sont très importants. Je rencontre un problème en supprimant un utilisateur de l'un de ces grands groupes. J'ai un programme de test qui illustre le problème. Notez que le groupe que je teste n'est pas imbriqué, mais user.IsMemberOf() semble également avoir le même problème, alors que GetAuthorizationGroups() affiche correctement les groupes dont un utilisateur est membre. Le groupe en question a environ 81K membres, ce qui est plus que ce qu'il aurait dû puisque Remove() ne fonctionne pas, et sera normalement d'environ 65K.GroupPrincipal.Members.Remove() ne fonctionne pas avec un grand groupe AD

Je serais intéressé d'entendre d'autres personnes qui ont eu ce problème et l'ont résolu. J'ai un cas ouvert avec Microsoft, mais l'appel est lent car le centre d'appel a environ 17 heures de décalage horaire, de sorte qu'ils n'arrivent pas au travail avant environ une heure avant de partir pour la maison.

using (var context = new PrincipalContext(ContextType.Domain)) 
{ 
    using (var group = GroupPrincipal.FindByIdentity(context, groupName)) 
    { 
     using (var user = UserPrincipal.FindByIdentity(context, userName)) 
     { 
      if (user != null) 
      { 
       var isMember = user.GetAuthorizationGroups() 
            .Any(g => g.DistinguishedName == group.DistinguishedName); 
       Console.WriteLine("1: check for membership returns: {0}", isMember); 
       if (group.Members.Remove(user)) 
       { 
        Console.WriteLine("user removed successfully"); 
        group.Save(); 
       } 
       else 
       { 
        // do save in case Remove() is lying to me 
        group.Save(); 
        Console.WriteLine("user remove failed"); 
        var isStillMember = user.GetAuthorizationGroups() 
              .Any(g => g.DistinguishedName == group.DistinguishedName); 
        Console.WriteLine("2: check for membership returns: {0}", isStillMember); 

       } 
      } 
     } 
    } 
} 
+0

Si j'étais vous je jetterais un coup d'oeil à l'espace de noms System.DirectoryServices.Protocols en traitant avec le groupe qui est aussi grand que le vôtre. Le code est plus difficile à écrire, mais vous utiliserez l'interface LDAP native qui peut être beaucoup plus efficace dans votre cas. MSDN a un excellent guide @ http://msdn.microsoft.com/en-us/library/bb332056.aspx. –

Répondre

4

Transforme ce bogue dans le code GroupPrincipal.Members.Remove() dans lequel échoue pour supprimer un groupe avec plus de 1500 membres. Cela a été corrigé dans .NET 4.0 Beta 2. Je ne sais pas s'ils ont prévu de reporter le portage du correctif sur 2.0/3.x. Le travail consiste à obtenir DirectoryEntry sous-jacent, puis utilisez Invoke pour exécuter la commande Remove sur l'objet IADsGroup.

var entry = group.GetUnderlyingObject() as DirectoryEntry; 
var userEntry = user.GetUnderlyingObject() as DirectoryEntry; 
entry.Invoke("Remove", new object[] { user.Path }); 
+0

Salut tvanfosson, pourriez-vous s'il vous plaît me montrer l'URL de l'affaire que vous avez connecté avec Microsoft? Nous rencontrons un problème qui vous ressemble, et nous aimerions vérifier si un correctif est disponible pour .net3.5 avant d'essayer la solution de contournement. J'ai été Bing et Google le Web, mais n'a pas trouvé de suivi lié à MS pour ce problème. – Ricky

+0

Le cas a été effectivement soumis par notre équipe sysadmin. Je n'ai pas l'URL. On m'a dit à l'époque qu'ils n'allaient pas ramener le correctif à 3.5, cependant. Oui, je leur ai demandé de le faire. – tvanfosson

0
public bool RemoveUserFromGroup(string UserName, string GroupName) 
{ 
    bool lResult = false; 
    if (String.IsNullOrEmpty(UserName) || String.IsNullOrEmpty(GroupName)) return lResult; 
    try 
    { 
     using (DirectoryEntry dirEntry = GetDirectoryEntry()) 
     { 
     using (DirectoryEntry dirUser = GetUser(UserName)) 
     { 
      if (dirEntry == null || dirUser == null) 
      { 
       return lResult; 
      } 
      using (DirectorySearcher deSearch = new DirectorySearcher()) 
      { 
       deSearch.SearchRoot = dirEntry; 
       deSearch.Filter = String.Format("(&(objectClass=group) (cn={0}))", GroupName); 
       deSearch.PageSize = 1000; 
       SearchResultCollection result = deSearch.FindAll(); 
       bool isAlreadyRemoved = false; 
       String sDN = dirUser.Path.Replace("LDAP://", String.Empty); 
       if (result != null && result.Count > 0) 
       { 
        for (int i = 0; i < result.Count; i++) 
        { 
        using (DirectoryEntry dirGroup = result[i].GetDirectoryEntry()) 
        { 
         String sGrDN = dirGroup.Path.Replace("LDAP://", String.Empty); 
         if (dirUser.Properties[Constants.Properties.PROP_MEMBER_OF].Contains(sGrDN)) 
         { 
          dirGroup.Properties[Constants.Properties.PROP_MEMBER].Remove(sDN); 
          dirGroup.CommitChanges(); 
          dirGroup.Close(); 
          lResult = true; 
          isAlreadyRemoved = true; 
          break; 
         } 
        } 
        if (isAlreadyRemoved) 
         break; 
        } 
       } 
      } 
     } 
     } 
    } 
    catch 
    { 
     lResult= false; 
    } 
    return lResult; 
} 
+0

Fournir simplement un code n'est pas une très bonne réponse. S'il vous plaît, essayez d'expliquer ce qu'il fait et pourquoi. – Yuriy

0

Ce poste m'a aidé à pointer dans la bonne direction, je voulais juste ajouter des informations d'addition.

Il fonctionne également directement au groupe et vous pouvez l'utiliser pour ajouter des membres de groupe.

using (var groupEntry = new DirectoryEntry(groupLdapPath)) 
{ 
    groupEntry.Invoke("remove", new object[] { memberLdapPath }); 
    groupEntry.Invoke("add", new object[] { memberLdapPath }); 
} 

Il faut aussi savoir, avec l'attribut standard « membre », vous utilisez l'utilisateur ou d'un groupe distinguishedName, mais invoquez nécessite le chemin avec LDAP: // préfixe, sinon il jette un InnerException vague:

Exception from HRESULT: 0x80005000 
Questions connexes