Domanda

Sto utilizzando il System.DirectoryServices.AccountManagement classi namespace per gestire l'appartenenza di diversi gruppi. Questi gruppi di controllo della popolazione del nostro sistema di contabilità di stampa e alcuni di essi sono molto grandi. Io corro in un problema di rimuovere qualsiasi utente da uno di questi grandi gruppi. Ho un programma di test che illustra il problema. Si noti che il gruppo sto testando non è nidificato, ma user.IsMemberOf () sembra anche avere lo stesso problema, mentre GetAuthorizationGroups () mostra correttamente i gruppi di un utente è un membro di. Il gruppo in questione ha circa 81K membri, che è più del dovuto dal Rimuovere () non funziona, e sarà normalmente circa 65K o così.

Sarei interessato a sentire da altre persone che hanno avuto questo problema e hanno risolto esso. Ho un caso aperto con Microsoft, ma la svolta intorno alla chiamata è lento in quanto il call center è di circa 17 ore di differenza di tempo in modo che non arrivano per il lavoro fino a circa un'ora prima di solito lascio per la casa.

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

                }
            }
        }
    }
}
È stato utile?

Soluzione

Risulta questo è un bug nel codice GroupPrincipal.Members.Remove (), in cui rimuovere non riesce per un gruppo con più di 1500 membri. Questo è stato risolto in .NET 4.0 Beta 2. Non so se hanno in programma di eseguire il porta la correzione in 2.0 / 3.x.

Il lavoro attorno è ottenere il DirectoryEntry sottostante, quindi utilizzare per richiamare per eseguire il comando Rimuovi sull'oggetto IADsGroup.

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

Altri suggerimenti

Questo post mi ha aiutato a puntare nella direzione giusta, volevo solo aggiungere alcune informazioni oltre.

Si lavora anche legandosi direttamente al gruppo, e lo si può utilizzare per aggiungere i membri del gruppo.

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

Anche essere consapevoli, con l'attributo standard 'membro', si utilizza l'utente o il gruppo distinguishedName, ma richiama richiede il percorso con LDAP: // prefix, altrimenti si getta un'InnerException vaga:

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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top