none
Workaround für GroupPrincipal.Members.Remove wenn mehr als 1500 Mitglieder enthalten sind RRS feed

  • Frage

  • Hallo zusammen,

    da es ja ein bekanntes Problem in .NET 3.5 SP1 ist, dass GroupPrincipals mit mehr als 1500 Membern das ein oder andere Problem haben (z.b. IsMember (false-positive), .Members.Remove)  interessiert mich, wie der Workaround dazu aussieht. Ich habe 3 Gruppen mit je ca. 3300 Usern und will daraus einzelne User entfernen.

    folgender Code wird ausgeführt ohne Exception, allerdings ist der User danach immer noch Mitglied in der AD-Gruppe:

                            myCurrentStandardGroup.Members.Remove(myUserPrincipal)
                            Try
                                myCurrentStandardGroup.Save()
                            Catch ex As Exception
                                Log(ex.ToString, 1)
                            End Try
    cu markus mayer
    Montag, 23. November 2009 11:00

Antworten

  • So, hab die Lösung jetzt selbst gefunden.

    Da die Members-Auflistung des GroupPrincipal ja eh nach 1500 Usern nicht funktioniert hat, habe ich die Prüfung schon über myGroupEntry.Invoke("IsMember", New Object() {myUserEntry.Path}) gemacht und das entfernen der User über das GroupPrincipal. Wahrscheinlich lag genau da der Fehler. Jetzt verwalte ich mein Benutzer über myCurrentGroupEntry.Invoke("Add", New Object() {myUserEntry.Path}) bzw. über myCurrentGroupEntry.Invoke("Remove", New Object() {myUserEntry.Path}), was dem direkten Aufruf der Methode des ADSI-Objects entspricht. Also auch nicht mehr "DirectoryEntry", sondern das tatsächliche COM-Objekt. Es läuft

    Vielen Dank an euch alle für die Hilfeversuche

    cu markus
    • Als Antwort markiert Markus_Mayer Montag, 23. November 2009 14:23
    Montag, 23. November 2009 14:23

Alle Antworten

  • Hallo Markus,


    da es ja ein bekanntes Problem in .NET 3.5 SP1 ist, dass GroupPrincipals mit mehr als 1500 Membern das ein oder andere Problem haben [...]

    das interessiert mich aber sehr. Könntest Du bitte einige Links zu den Problembeschreibungen posten? Und hast Du dein Code mit kleinen Gruppen ausprobiert und es funktioniert? Bis zu welcher Benutzeranzahl in der Gruppe? Ist das mit allen Gruppen der Fall? Noch eine Kleinigkeit: Warum beginnst du dein Try-Catch-Block erst vor Save()?

    Marcel

    Montag, 23. November 2009 12:01
  • http://bytes.com/topic/c-sharp/answers/249302-remove-user-group
    http://msdn.microsoft.com/en-us/library/ms676302(VS.85).aspx

    Die Members Auflistung in GroupPrincipal funktioniert bis 1500 User. Auch "IsMember" ist davon betroffen. Workaround siehe MSDN-Link. Ob es nur bei AD-Gruppen oder auch bei lokalen Gruppen funktioniert habe ich nicht ausprobiert. So wie ich das lese sind aber alle Gruppen betroffen.

    Der Try-Catch ist deshalb erst vor dem Save, da vorher die Änderungen nur in meinem Speicher durchgeführt werden und die evtl. auftretenden Fehler erst beim .Save stattfinden. Analog zu .SetInfo beim ADSI-Objekt.

    cu markus
    Montag, 23. November 2009 12:23
  • Hallo Markus_Meyer,

    Schau Dir mal die folgenden Links an. Vielleicht können Sie Dir weiter helfen.

    ADO range limits à http://www.rlmueller.net/DocumentLargeGroup.htm

    Aufzählen von Membern in einer großen Gruppe à http://msdn.microsoft.com/de-de/library/ms180907(VS.80).aspx

    Grüße,

    Robert

    Montag, 23. November 2009 12:55
    Moderator
  • Hallo Robert,

    und wie verhält sich das beim Hinzufügen bzw. Entfernen von Benutzern aus solch großen Gruppen?

    cu markus
    Montag, 23. November 2009 13:28
  • Danke für die Links, Markus.

    Die Seiten erklären leider nicht das von Dir gemeldete Verhalten von Members.Remove(). Der erste Link berichtet über eine *Exception*, die geworfen wird, sobald Remove() aufgerufen wird, die MSDN-Seite spricht gar nicht erst darüber, sondern bleibt bei der Enumeration. Eine Frage: Ist der myUserPrincipal, den Du aus der Gruppe entfernst, auch *tatsächlich* in der Mitglieder-Collection  deiner Gruppe vorhanden (ich meine unter den 1500,  s. Debug-Fenster)?

    [Das mit dem Try-Catch stimmt so nicht: Du kannst sehr wohl Ausnahmefehler erhalten, sieh dir mal PrincipalCollection.Remove(Principal principal)  im Reflector an.]

    Last edit: Remove() gibt einen boolschen Wert zurück, was erhälts Du denn?

    Montag, 23. November 2009 13:35
  • Hallo Marcel,

    Der/Die User sind definitiv in der AD-Gruppe enthalten. Hier die Prüfung:

    Dim myUserPrincipal As UserPrincipal = UserPrincipal.FindByIdentity(glbPrincipalContext, IdentityType.Name, thisClient.UserName)
    Dim myUserEntry As DirectoryEntry = myUserPrincipal.GetUnderlyingObject
    Dim myStandardGroup As GroupPrincipal = GroupPrincipal.FindByIdentity(glbPrincipalContext, IdentityType.Name, My.Settings.UserStandardGroupName)
    Dim myStandardGroupEntry As DirectoryEntry = myStandardGroup.GetUnderlyingObject
    
    Dim myIsStandardMember As Boolean = myStandardGroupEntry.Invoke("IsMember", New Object() {myUserEntry.Path})
    
    If myIsStandardMember Then
        myCurrentStandardGroup.Members.Remove(myUserPrincipal)
        myAdvancedGroup.Members.Add(myUserPrincipal)
        Try
            myCurrentStandardGroup.Save()
         Catch ex As Exception
            Log(ex.ToString, 1)
         End Try
         Try
            myAdvancedGroup.Save()
         Catch ex As Exception
            Log(ex.ToString, 1)
         End Try
         Log(String.Format("Changed Membership from ""{0}"" to ""{1}""", myCurrentStandardGroup.Name, myAdvancedGroup.Name), 1)
    End If
    


    Natürlich wird jedes Objekt dann noch auf "vorhanden" geprüft. Was in diesem Code passiert ist folgendes: Der User wird in die Advanced-Gruppe aufgenommen aber nicht aus der Standard entfernt. Es kommt keine Exception.

    cu markus

    p.s. Bei "Remove" hatte ich bisher keine Fehler, beim "Save" schon, war aber noch in der Debugger-Phase und ist mittlerweile nur noch ein "Rettungsring"
    Montag, 23. November 2009 13:52
  • Der/Die User sind definitiv in der AD-Gruppe enthalten.

    In der AD-Gruppe schon, das will ich auch nicht bezweifeln, aber auch in der PrincipalCollection myCurrentStandardGroup.Members? Setz mal ein Breakpoint auf die Zeile mit dem Remove() und sieh dir Members im Debugger an. Und was gibt Remove() zurück (wahr/falsch)?
    Montag, 23. November 2009 14:06
  • So, hab die Lösung jetzt selbst gefunden.

    Da die Members-Auflistung des GroupPrincipal ja eh nach 1500 Usern nicht funktioniert hat, habe ich die Prüfung schon über myGroupEntry.Invoke("IsMember", New Object() {myUserEntry.Path}) gemacht und das entfernen der User über das GroupPrincipal. Wahrscheinlich lag genau da der Fehler. Jetzt verwalte ich mein Benutzer über myCurrentGroupEntry.Invoke("Add", New Object() {myUserEntry.Path}) bzw. über myCurrentGroupEntry.Invoke("Remove", New Object() {myUserEntry.Path}), was dem direkten Aufruf der Methode des ADSI-Objects entspricht. Also auch nicht mehr "DirectoryEntry", sondern das tatsächliche COM-Objekt. Es läuft

    Vielen Dank an euch alle für die Hilfeversuche

    cu markus
    • Als Antwort markiert Markus_Mayer Montag, 23. November 2009 14:23
    Montag, 23. November 2009 14:23
  • Markus, ich freue mich, dass es nun funktioniert. Könntest Du aber vielleicht für andere Benutzer, die Deinen Post lesen werden noch kurz anführen, was der Rückgabewert von Remove() war und ob der Principal tatsächlich in der Collection war?
    Montag, 23. November 2009 14:50
  • Hallo Marcel,

    leider kann ich dir das nicht mehr liefern, da ich das Tool in der Live-Umgebung einsetze und jetzt schon komplet umgebaut habe. Das der User in der Members-Collection von dem GroupPrincipal enthalten war, bezweifel ich. Da bin ich beim Erstellen des Tools schon auf myGroupEntry.Invoke("IsMember", New Object() {myUserEntry.Path}) ausgewichen um ein verlässliches Ergebniss zu bekommen. Es ist gut möglich, dass Remove() als Ergebnis "False" zurückliefert. Hab ich nicht geprüft.

    Ich kann jedem nur empfehlen, alles was mit AD Bearbeitung über .NET zu tun hat ausführlich zu testen. Leider schweigt sich die MSDN-Doku über die Einschränkungen aus und man kommt erst auf die Hinweise mit den 1500 Mitgliedern, wenn man in den Fehler reingelaufen ist. Also ruhig in größeren Dimensionen denken und testen.

    Bei meinen Recherchen bin ich noch auf erheblich mehr Einschränkungen gestoßen. z.B. Gruppen mit mehr als 5000 Mitglliedern (http://technet.microsoft.com/en-us/library/bb727067.aspx), User mit mehr als 1016 (bin ich mir nicht mehr ganz sicher) Gruppen.
    Montag, 23. November 2009 15:31