I'm using System.DirectoryServices.AccountManagement
to query for a user and then find the groups for that user.
var _principalContext = new PrincipalContext(ContextType.Domain, domainAddress, adContainer, adQueryAccount, adQueryAccountPassword);
var user = UserPrincipal.FindByIdentity(_principalContext, IdentityType.SamAccountName, account);
var userGroups = user.GetGroups();
foreach (var group in userGroups.Cast<GroupPrincipal>())
{
//////////////////////////////////////////////////////
// getting the underlying DirectoryEntry shown
// to demonstrate that I can retrieve the underlying
// properties without the exception being thrown
DirectoryEntry directoryEntry = group.GetUnderlyingObject() as DirectoryEntry;
var displayName = directoryEntry.Properties["displayName"];
if (displayName != null && displayName.Value != null)
Console.WriteLine(displayName.Value);
//////////////////////////////////////////////////////
Console.WriteLine(group.DisplayName);// exception thrown here...
}
I can grab the underlying DirectoryEntry
object and dump its properties and values but as soon as the GroupPrincipal.DisplayName
property (or any property for that matter) is accessed, it throws the following exception:
"System.Runtime.InteropServices.COMException (0x8007200A): The specified directory service attribute or value does not exist.\r\n\r\n at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)\r\n at System.DirectoryServices.DirectoryEntry.Bind()\r\n at System.DirectoryServices.DirectoryEntry.get_SchemaEntry()\r\n at System.DirectoryServices.AccountManagement.ADStoreCtx.IsContainer(DirectoryEntry de)\r\n at System.DirectoryServices.AccountManagement.ADStoreCtx..ctor(DirectoryEntry ctxBase, Boolean ownCtxBase, String username, String password, ContextOptions options)\r\n at System.DirectoryServices.AccountManagement.PrincipalContext.CreateContextFromDirectoryEntry(DirectoryEntry entry)\r\n at System.DirectoryServices.AccountManagement.PrincipalContext.DoLDAPDirectoryInitNoContainer()\r\n at System.DirectoryServices.AccountManagement.PrincipalContext.DoDomainInit()\r\n at System.DirectoryServices.AccountManagement.PrincipalContext.Initialize()\r\n at System.DirectoryServices.Account Management.PrincipalContext.get_QueryCtx()\r\n at System.DirectoryServices.AccountManagement.Principal.HandleGet[T](T& currentValue, String name, LoadState& state)\r\n at System.DirectoryServices.AccountManagement.Principal.get_DisplayName()\r\n at ConsoleApplication9.Program.Main(String[] args)"
Why would I be able to dump the raw properties of the underlying DirectoryEntry
but not be able to call any of the properties directly on the GroupPrincipal
? What would cause this exception? Note that this does not happen on the "Domain Users" group but the subsequent groups, it does...
I found the solution. If I pass the context to the GetGroups
method, it works.
var user = UserPrincipal.FindByIdentity(_principalContext, IdentityType.SamAccountName, account);
var userGroups = user.GetGroups(_principalContext);
Apparently, this limits the groups retrieved to the domain associated with the context. Although this is not intuitive because the context was used to retrieve the user in the first place!!!
This leads me to believe there must be groups from other domains being returned previously and permissions were as such to prevent accessing that information.
Why are you using the .GetUnderlyingObject()
call? Seems totally superfluous... just use the .SamAccountName
property of the GroupPrincipal
directly...
Try this:
foreach (var group in userGroups.Cast<GroupPrincipal>())
{
Console.WriteLine(group.SamAccountName);
Console.WriteLine(group.DisplayName);
Console.WriteLine(group.IsSecurityGroup);
}
Seems a lot easier - no?
User contributions licensed under CC BY-SA 3.0