0

请你帮助我好吗?我正在尝试使用以下代码从远程计算机枚举 AD 组的成员:

using (var entry = new DirectoryEntry(..
{
    foreach (object member in (IEnumerable)entry.Invoke("Members", null))
    {

除了一个环境之外,此代码运行良好。

在这个特定的环境中,当我尝试枚举 AD 组的成员时,它会引发以下异常:

System.Reflection.TargetInvocationException:调用的目标已引发异常。

System.ArgumentException:值不在预期范围内。--- 内部异常堆栈跟踪结束 ---

在 System.DirectoryServices.DirectoryEntry.Invoke(字符串方法名,对象 [] 参数)

我通过 power shell(复制下面的脚本)运行相同的命令并得到相同的错误:

使用“2”参数调用“调用”的异常:“值不在预期范围内。

在 C:\Temp\PSTest_AD_Group_Members2.ps1:23 char:5

  • $members = $DirectoryEntry.Invoke("成员", $null)
  • CategoryInfo : NotSpecified: (:) [], MethodInvocationException
  • FullyQualifiedErrorId : DotNetMethodTargetInvocation

请注意

  1. 我尝试在不同域中的多个 DC 上复制它,但未成功。它只发生在一种特定的环境中
  2. 我尝试在线搜索此异常,但未找到任何相关内容
  3. 我正在使用域管理员来运行此代码
  4. 代码在最新更新的 Windows Server 2016 上运行
  5. 我有一个产生相同行为的 PowerShell 脚本(复制如下)
  6. 我在事件查看器中看不到任何相关条目,表明源计算机和目标计算机都出现问题

有人能帮我理解为什么这段代码只能在那个特定的环境中获得 AD 组的成员吗?

DC 方面有没有办法了解出了什么问题?也许是传入/尝试命令的 DC 日志?

谢谢你的帮助

=========================== powershell script ==============================

Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$cred = Get-Credential
$domain = "<domain name>"
$groupname = "<group name>"
$results = "<result csv file path>"

cls

$ctx = New-Object 'DirectoryServices.AccountManagement.PrincipalContext' ([DirectoryServices.AccountManagement.ContextType]::Domain, $domain, $cred.UserName, $cred.GetNetworkCredential().Password)
$timing = Measure-Command {$group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($ctx, $groupname)}
$props = [ordered]@{
    'Type' = $group.StructuralObjectClass
    'Name' = $group.SamAccountName
    'SID' = $group.sid
    'RetrivedIn(s)' = $timing.TotalSeconds
    'Retrievedcount' = $group.count
    'UserPrincipalName' = $group.UserPrincipalName
}
New-Object -TypeName PSObject -Property $props | Export-Csv -Path $results -NoTypeInformation

$timing = Measure-Command {
    $DirectoryEntry = New-Object System.DirectoryServices.DirectoryEntry ("LDAPS://$($group.DistinguishedName)", $cred.UserName, $cred.GetNetworkCredential().Password)
    
$members = $DirectoryEntry.Invoke("Members")
}

$props = [ordered]@{
    'Type' = $members.gettype().name
    'Name' = "GroupDirectoryEntry"
    'SID' = "n/a"
    'RetrivedIn(s)' = $timing.TotalSeconds
    'Retrievedcount' = ($members | Measure-Object).count
    'UserPrincipalName' = "n/a"
}
New-Object -TypeName PSObject -Property $props | Export-Csv -Path $results -Append -NoTypeInformation

$members |
ForEach-Object {
    $bytesSid = $_.gettype().InvokeMember("objectSid","GetProperty",$null,$_,$null)
    $sid = New-Object System.Security.Principal.SecurityIdentifier ($bytesSid, 0)
    $timing = Measure-Command {$acct = [DirectoryServices.AccountManagement.Principal]::FindByIdentity($ctx, 4, $sid.value)}
    $props = [ordered]@{
        'Type' = $acct.StructuralObjectClass
        'Name' = $acct.SamAccountName
        'SID' = $acct.Sid
        'RetrivedIn(s)' = $timing.TotalSeconds
        'Retrievedcount' = $acct.count
        'UserPrincipalName' = $acct.UserPrincipalName
    }
    New-Object -TypeName PSObject -Property $props | Export-Csv -Path $results -Append -NoTypeInformation
}
============================= end of powershell script ================================
4

2 回答 2

0

为什么不使用GroupPrincipal而不是反射?

就像这样简单:

PrincipalContext ctx = new PrincipalContext(ContextType.Domain,                                                                      
                                            "fabrikam.com",   
                                            "DC=fabrikam,DC=com",   
                                            "administrator",   
                                            "SecretPwd123");  

GroupPrincipal grp = GroupPrincipal.FindByIdentity(ctx,   
                                                   IdentityType.Name,   
                                                   "Domain Admins");  

if (grp != null)  
{  
    foreach (Principal p in grp.GetMembers(true))  
    {  
         Console.WriteLine(p.Name);  
    }  
    grp.Dispose();  
}  

ctx.Dispose();

该错误很容易解释:

调用的目标。那就是Members功能

System.ArgumentException:值不在预期范围内 这很可能是指该null值。

于 2020-10-04T15:06:18.280 回答
0

我找出问题所在。由于使用了准备其活动目录以获得支持的第三方产品,问题环境在其 AD 环境中进行了自定义。作为集成的一部分,它运行架构更新,将“成员”属性添加到其 AD 架构。当我们在目录条目上调用成员时,这会导致冲突。

于 2020-10-15T12:32:28.227 回答