问题
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?
回答1:
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.
回答2:
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;
}
来源:https://stackoverflow.com/questions/4518472/userprincipal-getgroups-fails-with-unknown-error