4

System.DirectoryServices.AccountManagement用来查询用户,然后找到该用户的组。

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

我可以抓取底层DirectoryEntry对象并转储其属性和值,但是一旦GroupPrincipal.DisplayName访问该属性(或与此相关的任何属性),它就会引发以下异常:

"System.Runtime.InteropServices.COMException (0x8007200A):指定的目录服务属性或值不存在。\r\n\r\n 在 System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)\r\n 在 System。 DirectoryServices.DirectoryEntry.Bind()\r\n 在 System.DirectoryServices.DirectoryEntry.get_SchemaEntry()\r\n 在 System.DirectoryServices.AccountManagement.ADStoreCtx.IsContainer(DirectoryEntry de)\r\n 在 System.DirectoryServices.AccountManagement。 ADStoreCtx..ctor(DirectoryEntry ctxBase, Boolean ownCtxBase, String username, String password, ContextOptions options)\r\n 在 System.DirectoryServices.AccountManagement.PrincipalContext.CreateContextFromDirectoryEntry(DirectoryEntry entry)\r\n 在 System.DirectoryServices.AccountManagement.PrincipalContext .DoLDAPDirectoryInitNoContainer()\r\n 在 System.DirectoryServices.AccountManagement.PrincipalContext.DoDomainInit()\r\n 在 System.DirectoryServices.AccountManagement.PrincipalContext.Initialize()\r\n 在 System.DirectoryServices.Account Management.PrincipalContext.get_QueryCtx ()\r\n 在 System.DirectoryServices.AccountManagement.Principal.HandleGet[T](T& currentValue, String name, LoadState& state)\r\n 在 System.DirectoryServices.AccountManagement.Principal.get_DisplayName()\r\n 在ConsoleApplication9.Program.Main(String[] args)"AccountManagement.Principal.HandleGet[T](T& currentValue, String name, LoadState& state)\r\n 在 System.DirectoryServices.AccountManagement.Principal.get_DisplayName()\r\n 在 ConsoleApplication9.Program.Main(String[] args) "AccountManagement.Principal.HandleGet[T](T& currentValue, String name, LoadState& state)\r\n 在 System.DirectoryServices.AccountManagement.Principal.get_DisplayName()\r\n 在 ConsoleApplication9.Program.Main(String[] args) "

为什么我可以转储底层的原始属性,DirectoryEntry但不能直接调用任何属性GroupPrincipal?什么会导致这个异常?请注意,这不会发生在“域用户”组上,而是发生在后续组上,它确实......

4

2 回答 2

6

我找到了解决方案。如果我将上下文传递给该GetGroups方法,它就可以工作。

var user = UserPrincipal.FindByIdentity(_principalContext, IdentityType.SamAccountName, account);
var userGroups = user.GetGroups(_principalContext);

显然,这将检索到的组限制为与上下文关联的域。虽然这并不直观,因为上下文首先用于检索用户!!!

这使我相信之前必须返回来自其他域的组,并且权限本身就是为了防止访问该信息。

于 2013-04-17T21:10:38.040 回答
0

你为什么用这个.GetUnderlyingObject()电话?似乎完全是多余的......只需使用直接的.SamAccountName属性GroupPrincipal......

尝试这个:

foreach (var group in userGroups.Cast<GroupPrincipal>())
{
    Console.WriteLine(group.SamAccountName);
    Console.WriteLine(group.DisplayName);
    Console.WriteLine(group.IsSecurityGroup);
}

似乎容易多了——不是吗?

于 2013-04-17T20:25:55.967 回答