GroupPrincipal.Members.Remove()不适用于大型AD组

tva*_*son 5 .net c# active-directory account-management

我正在使用System.DirectoryServices.AccountManagement命名空间类来管理多个组的成员身份.这些群体控制着我们的印刷会计系统的人口,其中一些非常庞大.我遇到了从这些大型组中删除任何用户的问题.我有一个测试程序来说明问题.请注意,我正在测试的组不是嵌套的,但user.IsMemberOf()似乎也有同样的问题,而GetAuthorizationGroups()正确显示用户所属的组.有问题的小组有大约81,000名成员,因为Remove()不起作用,所以它应该超过它应该有的,并且通常大约是65K左右.

我有兴趣听到有其他人遇到过这个问题并已经解决了.我有一个与微软打开的案例,但由于呼叫中心的时间差大约为17小时,因此呼叫转向很慢,因此他们在我离开家之前大约一个小时才到达工作岗位.

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

                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

tva*_*son 5

事实证明这是GroupPrincipal.Members.Remove()代码中的一个错误,其中对于具有超过1500个成员的组,删除失败.这已在.NET 4.0 Beta 2中修复.我不知道他们是否有计划将修复程序反向移植到2.0/3.x.

解决方法是获取底层DirectoryEntry,然后使用Invoke在IADsGroup对象上执行Remove命令.

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