Frage

Ich benutze das System.DirectoryServices.AccountManagement Namespace -Klassen zur Verwaltung der Mitgliedschaft mehrerer Gruppen. Diese Gruppen kontrollieren die Bevölkerung unseres Druckbuchhaltungssystems und einige von ihnen sind sehr groß. Ich stehe in ein Problem damit, einen Benutzer aus einer dieser großen Gruppen zu entfernen. Ich habe ein Testprogramm, das das Problem veranschaulicht. Beachten Sie, dass die Gruppe, die ich teste, nicht verschachtelt ist, aber user.ismemberof () scheint das gleiche Problem zu haben, während GetAuthorizationGroups () den Gruppen, von denen ein Benutzer ein Mitglied ist, korrekt anzeigt. Die fragliche Gruppe hat ungefähr 81K -Mitglieder, was mehr als seitdem entfernen () funktioniert und normalerweise ungefähr 65.000 sein wird.

Ich würde mich von anderen Menschen interessieren, die dieses Problem hatten und es gelöst haben. Ich habe einen offenen Gehäuse mit Microsoft, aber die Wende am Anruf ist langsam, da das Callcenter etwa 17 Stunden Zeitunterschied beträgt, sodass sie erst eine Stunde vor meiner Normalität zur Arbeit ankommen.

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 );

                }
            }
        }
    }
}
War es hilfreich?

Lösung

Es stellt sich heraus, dass dies ein Fehler im Coupprincipal.MEMBERS.REMOVE () -Code ist, in dem Entfernung für eine Gruppe mit mehr als 1500 Mitgliedern fehlschlägt. Dies wurde in .NET 4.0 Beta 2 festgelegt. Ich weiß nicht, ob sie Pläne haben, das Fix in 2.0/3.x zu portieren.

Die Arbeit besteht darin, das zugrunde liegende Verzeichnisertrag zu erhalten und dann den Befehl entfernen im IADSGroup -Objekt auszuführen.

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

Andere Tipps

Dieser Beitrag hat mir geholfen, in die richtige Richtung zu richten, wollte nur einige Hinzufügungsinformationen hinzufügen.

Es funktioniert auch direkt an die Gruppe und Sie können es zum Hinzufügen von Gruppenmitgliedern verwenden.

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

Beachten Sie auch, dass Sie mit dem Standard -Attribut "Mitglied" den Benutzer- oder Gruppenunterschiedsname verwenden, aber aufrufen erfordert den Pfad mit LDAP: // Präfix, ansonsten wirft es eine vage Innerexception:

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;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top