22

I am trying to get all Active Directory groups for a user, with the following code:

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

This code correctly finds the user principal, but fails when GetGroups is called with a PrincipalOperationException: Unknown error (0x80005000).

Root exception:

   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]

Inner exception (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.

Any clues?

Community
  • 1
  • 1
Holstebroe
  • 4,993
  • 4
  • 29
  • 45
  • 1
    Does it happen on all users? Or it happen on a particular user only? I know there is a bug in .NET library that it throws this COMException when the user DN contains "/". I also have a fix on this issue if you confirm this happens only on the user with DN containing "/" only – Harvey Kwok Dec 24 '10 at 07:32
  • I have the issue you describe. I have the problem getting groups when user DN contains "/". Can you tell me what's the fix you use please? – Lamelas84 Jan 31 '17 at 09:04
  • I have the same issue for users containing "/" in DN. What was the fix? – bahramzy Apr 20 '17 at 11:38
  • I didn't get an answer from Harvey Kwok. Still having problems with this. – Lamelas84 May 15 '17 at 14:20

2 Answers2

33

Adding Environment.UserDomainName as the name argument to the PrincipalContext helped:

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

I still don't know why PrincipalContext(ContextType.Domain) only works for finding the UserPrincipal and not the groups of the user. The COM error message "unknown error" is not very helpful and the PrincipalContext constructor overload with only the ContextType is virtually undocumented at MSDN. It smells like an issue with the .NET framework as pointed out by Harvey Kwok.

Holstebroe
  • 4,993
  • 4
  • 29
  • 45
  • Had exactly the same outcome from `UserPrincipal.IsMemberOf( GroupPrincipal )` call when current user is not a member. Indeed, using `PrincipalContext( ContextType, string )` constructor resolves the internal problem! – Astrogator Jun 21 '16 at 16:38
  • Also had this exact problem. It would randomly throw `DirectoryServicesCOMException` with `HRESULT 0x80072030` or converted from `uint` to `int` it is `.ErrorCode == -2147016656`. Happened only in production but not on dev VMs with slow connection to the AD. Using the `PrincipalContext(ContextType, string)` .ctor seems finally to have resolved the issue. – Brian Reiter Jan 05 '17 at 14:20
3

As mentioned in the question comments, another reason this particular error can happen when calling GetGroups is due to a documented bug in .NET and .NET Core. It happens when attempting to get groups for user principals that have a slash ('/') in their AD Distinguished Name.

The workaround, at least until the bug is fixed, is to write your own GetGroups method. Here is a working example that returns just the group names (also includes distribution lists):

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;
}
Tawab Wakil
  • 1,737
  • 18
  • 33
  • how do get the rest of the group details like group description, scope etc.? – Varsh Aug 11 '21 at 11:32
  • 1
    @Varsh You can only get the group names and OUs this way. For other info like description, try using the method described [here](https://stackoverflow.com/questions/8474718/listing-all-active-directory-groups). When you use that and create your `GroupPrincipal`, if you only want the info from one group instead of all, just set the group name property before running the search. – Tawab Wakil Aug 11 '21 at 16:32
  • bug is fixed ? Or must be use workaround ? – Kiquenet Oct 26 '22 at 12:35
  • Not fixed, apparently: https://github.com/dotnet/runtime/issues/25887 – Tawab Wakil Oct 26 '22 at 14:19