UserPrincipal.GetGroups fails with unknown error
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;
}
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.