Question

J'utilise le System.DirectoryServices.AccountManagement cours d'espace de noms pour gérer les membres 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 grandes. Je suis en cours d'exécution dans un problème supprimant tout utilisateur d'un de ces grands groupes. J'ai un programme de test qui illustre le problème. Notez que le groupe je teste est pas imbriqué, mais user.IsMemberOf () semble également avoir le même problème, alors que GetAuthorizationGroups () correctement montre les groupes dont un utilisateur est membre. Le groupe en question a environ 81K membres, ce qui est plus que ce qu'elle devrait avoir depuis remove () ne fonctionne pas, et normalement environ 65K environ.

Je serais intéressé d'entendre d'autres personnes qui ont eu ce problème et ont résolu ce. J'ai un cas ouvert avec Microsoft, mais le tour autour de l'appel est lent depuis le centre d'appel est d'environ 17 heures de décalage horaire afin qu'ils n'arrivent pas pour le travail jusqu'à environ une heure avant que je parte en général 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 );

                }
            }
        }
    }
}
Était-ce utile?

La solution

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 des plans pour le port back le correctif dans 2.0 / 3.x.

Le travail est là pour obtenir le sous-jacent DirectoryEntry, puis utilisez Invoke pour exécuter la commande Supprimer l'objet IADsGroup.

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

Autres conseils

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

Il travaille également liant directement au groupe, et vous pouvez l'utiliser pour ajouter des membres du 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
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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top