Pergunta

Estou usando o System.DirectoryServices.AccountManagement Classes de namespace para gerenciar a associação de vários grupos. Esses grupos controlam a população do nosso sistema de contabilidade impressos e alguns deles são muito grandes. Estou tendo um problema para remover qualquer usuário de um desses grandes grupos. Eu tenho um programa de teste que ilustra o problema. Observe que o grupo que estou testando não está aninhado, mas o user.MememberOf () também parece ter o mesmo problema, enquanto o getAuthorizationGroups () mostra corretamente que os grupos dos quais um usuário é um membro. O grupo em questão tem cerca de 81 mil membros, o que é mais do que deveria ter removido () não está funcionando, e normalmente terá cerca de 65 mil ou mais.

Eu estaria interessado em ouvir de outras pessoas que tiveram esse problema e o resolveram. Eu tenho um estojo aberto com a Microsoft, mas a reviravolta na chamada é lenta, já que o call center tem cerca de 17 horas de diferença de horário, para que eles não cheguem para o trabalho até cerca de uma hora antes de eu geralmente sair para 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 );

                }
            }
        }
    }
}
Foi útil?

Solução

Acontece que este é um bug no código GroupPrincipal.members.remove () no qual remover falha para um grupo com mais de 1500 membros. Isso foi corrigido no .NET 4.0 Beta 2. Não sei se eles têm planos de fazer o apoio da correção para 2.0/3.x.

O trabalho é obter o diretório subjacente e, em seguida, usar o Invoke para executar o comando Remover no objeto IDSGroup.

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

Outras dicas

Este post ajudou -me a apontar na direção certa, só queria adicionar algumas informações adicionais.

Ele também trabalha ligando -se diretamente ao grupo e você pode usá -lo para adicionar membros do grupo.

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

Também esteja ciente, com o atributo 'membro' padrão, você usa o usuário ou o grupo DistinguishedName, mas a Invoke requer o caminho com o prefixo LDAP: //, caso contrário, ele lança uma vaga 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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top