【问题标题】:UserPrincipal.GetGroups fails with unknown errorUserPrincipal.GetGroups 失败,出现未知错误
【发布时间】:2010-12-23 11:49:01
【问题描述】:

我正在尝试使用以下代码获取用户的所有 Active Directory 组:

    private static IEnumerable<string> GetGroupNames(string userName)
    {
        using (var context = new PrincipalContext(ContextType.Domain))
        {
            using (var userPrincipal = UserPrincipal.FindByIdentity(context, userName))
            {
                var groupSearch = userPrincipal.GetGroups(context);
                var result = new List<string>();
                foreach (var principal in groupSearch)
                {
                    Log.LogDebug("User {0} is member of group {0}", userPrincipal.DisplayName, principal.DisplayName);
                    result.Add(principal.SamAccountName);
                }
                return result;
            }
        }
    }

此代码正确找到用户主体,但在调用 GetGroups 时失败,并出现 PrincipalOperationException: Unknown error (0x80005000)。

根异常:

   at System.DirectoryServices.AccountManagement.ADStoreCtx.GetGroupsMemberOf(Principal foreignPrincipal, StoreCtx foreignContext)
   at System.DirectoryServices.AccountManagement.Principal.GetGroupsHelper(PrincipalContext contextToQuery)
   at System.DirectoryServices.AccountManagement.Principal.GetGroups(PrincipalContext contextToQuery)
   at [line of the GetGroup call]

内部异常(COMException):

   at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
   at System.DirectoryServices.DirectoryEntry.Bind()
   at System.DirectoryServices.DirectoryEntry.get_AdsObject()
   at System.DirectoryServices.PropertyValueCollection.PopulateList()
   at System.DirectoryServices.PropertyValueCollection..ctor(DirectoryEntry entry, String propertyName)
   at System.DirectoryServices.PropertyCollection.get_Item(String propertyName)
   at System.DirectoryServices.AccountManagement.ADUtils.RetriveWkDn(DirectoryEntry deBase, String defaultNamingContext, String serverN

Another report with this problem.

有什么线索吗?

【问题讨论】:

  • 所有用户都会出现这种情况吗?或者它只发生在特定用户身上?我知道 .NET 库中有一个错误,当用户 DN 包含“/”时它会抛出这个 COMException。如果您确认此问题仅发生在 DN 仅包含“/”的用户上,我也对此问题进行了修复
  • 我有你描述的问题。当用户 DN 包含“/”时,我在获取组时遇到问题。你能告诉我你使用的修复方法是什么吗?
  • 我对在 DN 中包含“/”的用户有同样的问题。解决方法是什么?
  • 我没有得到 Harvey Kwok 的答复。仍然有这个问题。

标签: .net active-directory directoryservices


【解决方案1】:

添加 Environment.UserDomainName 作为 PrincipalContext 的名称参数有助于:

using (var context = new PrincipalContext(ContextType.Domain, Environment.UserDomainName))

我仍然不知道为什么 PrincipalContext(ContextType.Domain) 仅适用于查找 UserPrincipal 而不是用户组。 COM 错误消息“未知错误”不是很有帮助,只有 ContextType 的 PrincipalContext 构造函数重载在 MSDN 中几乎没有记录。正如 Harvey Kwok 所指出的,这听起来像是 .NET 框架的问题。

【讨论】:

  • 当当前用户不是会员时,UserPrincipal.IsMemberOf( GroupPrincipal ) 调用的结果完全相同。确实,使用PrincipalContext( ContextType, string )构造函数解决了内部问题!
  • 也有这个确切的问题。它会随机抛出DirectoryServicesCOMExceptionHRESULT 0x80072030 或从uint 转换为int 它是.ErrorCode == -2147016656。仅在生产中发生,而不是在与 AD 连接缓慢的开发 VM 上发生。使用PrincipalContext(ContextType, string) .ctor 似乎终于解决了这个问题。
【解决方案2】:

正如问题 cmets 中所述,调用GetGroups 时可能发生此特定错误的另一个原因是由于a documented bug in .NET and .NET Core。尝试为 AD 可分辨名称中带有斜杠 ('/') 的用户主体获取组时会发生这种情况。

至少在修复错误之前,解决方法是编写自己的GetGroups 方法。这是一个只返回组名(还包括分发列表)的工作示例:

public static List<string> GetGroups(UserPrincipal user)
{
    List<string> groupNames = new List<string>();

    using (DirectoryEntry directoryEntryUser = (DirectoryEntry)user.GetUnderlyingObject())
    {
        object[] groups = GetAdPropertyValueObjectArray(directoryEntryUser, "memberOf");
        const int prefixLength = 3;
        const string prefix = "CN=";  // CN = Common Name

        if (groups != null)
        {
            foreach (string group in groups)
            {
                if (group.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
                {
                    int commaIndex = group.IndexOf(",", prefixLength);
                    string groupName;

                    if (commaIndex >= 0)
                        groupName = group.Substring(prefixLength, commaIndex - prefixLength);
                    else
                        groupName = group.Substring(prefixLength);

                    if (groupName.Length > 0)
                        groupNames.Add(groupName);
                }
            }
        }
    }

    return groupNames;
}

private static object[] GetAdPropertyValueObjectArray(DirectoryEntry userAccount, string adPropertyKey)
{
    object[] result = null;
    PropertyValueCollection property = userAccount.Properties[adPropertyKey];

    if (property != null)
    {
        object propertyValue = property.Value;

        if (propertyValue != null)
        {
            if (propertyValue is string)
            {
                result = new object[1];
                result[0] = propertyValue;
            }
            else
            {
                result = (object[])propertyValue;
            }
        }
    }

    return result;
}

【讨论】:

  • 如何获取其他组详细信息,如组描述、范围等?
  • @Varsh 你只能通过这种方式获取组名和OU。对于描述等其他信息,请尝试使用here 描述的方法。当您使用它并创建您的 GroupPrincipal 时,如果您只想要一组而不是全部的信息,只需在运行搜索之前设置组名称属性。
  • 感谢您的回复。我去看看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-08
  • 2016-07-28
  • 1970-01-01
  • 2012-03-11
相关资源
最近更新 更多