UserPrincipal.GetGroups завершается с неизвестной ошибкой - PullRequest
19 голосов
/ 23 декабря 2010

Я пытаюсь получить все группы 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: неизвестная ошибка(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

Еще одно сообщение с этой проблемой .

Есть какие-нибудь подсказки?

Ответы [ 2 ]

31 голосов
/ 27 декабря 2010

Добавление Environment.UserDomainName в качестве аргумента имени к PrincipalContext помогло:

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

Я до сих пор не знаю, почему PrincipalContext (ContextType.Domain) работает только для нахождения UserPrincipal, а не для групппользователь.Сообщение об ошибке COM «неизвестная ошибка» не очень полезно, и перегрузка конструктора PrincipalContext только с ContextType фактически недокументирована в MSDN.Как отмечает Харви Квок, он пахнет проблемой с платформой .NET.

0 голосов
/ 21 февраля 2019

Как уже упоминалось в комментариях к вопросу, еще одна причина, по которой эта конкретная ошибка может возникать при вызове GetGroups, связана с документированной ошибкой в ​​.NET и .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;
}
...