如何避免groupPrincipal.Members.Add引发NoMatchingPrincipalException

本文关键字:引发 NoMatchingPrincipalException Add Members 何避免 groupPrincipal | 更新日期: 2023-09-27 17:58:51

我有一个Active Directory域,在其中我在某个新创建的OU下创建组对象,如下所示,例如SubOuB下的组。GlobalGroups下的全局组已经存在。

+MainOu
   +--SubOuA
     +--GroupA_A
     +--GroupA_B
     +--GroupA_C
  +--SubOuB
     +--GroupB_A
     ...
+GlobalGroups
  +--GlobalGroupA
  +--GlobalGroupB
  ...

现在,我想将新建OU下新添加的组作为成员添加到其中一个全局组中,例如将GroupA_A作为成员添加至GlobalGroupB:

using( PrincipalContext principalContext =
    new PrincipalContext( ContextType.Domain, Environment.UserDomainName ) )
{
    GroupPrincipal groupPrincipal = GroupPrincipal.FindByIdentity(
        principalContext, "GlobalGroupB" );
    if( groupPrincipal != null )
    {
        // Target group found.
        groupPrincipal.Members.Add( principalContext, IdentityType.Name, "GroupA_A" );
        // The next line throws a NoMatchingPrincipalException.
        groupPrincipal.Save();
    }
}

当我看到AD结构和对象时,我可以看到这两个对象。ADSI编辑器显示两个"名称"都是正确的。在创建新的OU和组对象后,当我在测试应用程序中手动单独运行代码时,将组作为成员添加到全局组也可以很好地工作。我使用的所有代码都在具有相同结构的AD的暂存环境中工作,所以我不确定为什么它在生产环境中会出现问题。

有什么想法吗?我已经看到DirectoryEntry对象有一个RefreshCache方法,它强制重新加载特定对象的属性值,但我认为这在这里没有帮助。我的问题是时间问题吗?我是否可以强制"重新加载"现有对象,以便找到新创建的组并将其添加到全局组中?

更新

这似乎肯定是AD同步的一个问题——当我不断检查新创建的组对象的存在时(例如,使用Thread.Sleep(1000)的循环),我的代码按预期工作。缺点是我不知道要等多久(在我的环境中,测试时间在6到15秒之间),我也认为这是一种非常肮脏的方法。不幸的是,我找不到任何关于如何"刷新"AD对象或"刷新"缓存的信息。

更新2

当我连接到特定的域控制器时,第一个查询速度较慢(3000多毫秒),随后的查询速度较快,返回所需时间大致相同。我仍然不知道如何避免定期查询AD,直到期望的对象确实可用(作为查询结果)。

如何避免groupPrincipal.Members.Add引发NoMatchingPrincipalException

据我所知,解决问题的唯一方法如下:

  • 按照我的问题中的建议进行操作,并定期查询"您的"域控制器,直到期望的对象可用或达到可配置的超时为止
  • 通过Domain.DomainControllers检索所有可用的域控制器,并查询每个域控制器,直到找到对象为止

我不太喜欢这两种方式,但我找不到其他选择。请随时提出更好的替代方案。