无法使用 C# 枚举 AD 组的成员
Failure to enumerate AD Group's members using C#
你能帮帮我吗?我正在尝试使用以下代码从远程计算机枚举 AD 组的成员:
using (var entry = new DirectoryEntry(..
{
foreach (object member in (IEnumerable)entry.Invoke("Members", null))
{
除一种环境外,此代码运行良好。
在这个特定的环境中,当我尝试枚举 AD 组的成员时,它抛出以下异常:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
System.ArgumentException: Value does not fall within the expected range.
--- End of inner exception stack trace ---
at System.DirectoryServices.DirectoryEntry.Invoke(String methodName, Object[] args)
我 运行 通过 power shell 执行相同的命令(下面复制的脚本)并得到相同的错误:
Exception calling "Invoke" with "2" argument(s): "Value does not fall within the expected range.
At C:\Temp\PSTest_AD_Group_Members2.ps1:23 char:5
- $members = $DirectoryEntry.Invoke("Members", $null)
-
- CategoryInfo : NotSpecified: (:) [], MethodInvocationException
- FullyQualifiedErrorId : DotNetMethodTargetInvocation
请注意
- 我尝试在不同域的多个 DC 上重现它,但没有成功。它只发生在一个特定的环境中
- 我尝试在线搜索此异常,但没有找到任何相关内容
- 我正在使用域管理员来运行此代码
- 代码是 运行ning on Windows Server 2016 with latest updates
- 我有一个产生相同行为的 PowerShell 脚本(在下面复制)
- 我在事件查看器中没有看到相关条目,表明源计算机和目标计算机都出现了问题
谁能帮我理解为什么这段代码无法仅在那个特定环境中获取 AD 组的成员?
DC 端有没有办法了解哪里出了问题?也许是 incoming/attempted 命令的 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 ================================
为什么不使用 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();
错误解释得很清楚:
target of an invocation.
That is the Members
function
System.ArgumentException: Value does not fall within the expected range
This most probably refers to the null
value.
我找出问题所在。
由于使用 third-party 产品准备其活动目录以获得支持,问题环境在其 AD 环境中进行了自定义。作为集成的一部分,它 运行 架构更新,将“成员”属性添加到他们的 AD 架构中。
当我们在目录条目上调用成员时,这会导致冲突。
你能帮帮我吗?我正在尝试使用以下代码从远程计算机枚举 AD 组的成员:
using (var entry = new DirectoryEntry(..
{
foreach (object member in (IEnumerable)entry.Invoke("Members", null))
{
除一种环境外,此代码运行良好。
在这个特定的环境中,当我尝试枚举 AD 组的成员时,它抛出以下异常:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
System.ArgumentException: Value does not fall within the expected range. --- End of inner exception stack trace ---
at System.DirectoryServices.DirectoryEntry.Invoke(String methodName, Object[] args)
我 运行 通过 power shell 执行相同的命令(下面复制的脚本)并得到相同的错误:
Exception calling "Invoke" with "2" argument(s): "Value does not fall within the expected range.
At C:\Temp\PSTest_AD_Group_Members2.ps1:23 char:5
- $members = $DirectoryEntry.Invoke("Members", $null)
- CategoryInfo : NotSpecified: (:) [], MethodInvocationException
- FullyQualifiedErrorId : DotNetMethodTargetInvocation
请注意
- 我尝试在不同域的多个 DC 上重现它,但没有成功。它只发生在一个特定的环境中
- 我尝试在线搜索此异常,但没有找到任何相关内容
- 我正在使用域管理员来运行此代码
- 代码是 运行ning on Windows Server 2016 with latest updates
- 我有一个产生相同行为的 PowerShell 脚本(在下面复制)
- 我在事件查看器中没有看到相关条目,表明源计算机和目标计算机都出现了问题
谁能帮我理解为什么这段代码无法仅在那个特定环境中获取 AD 组的成员?
DC 端有没有办法了解哪里出了问题?也许是 incoming/attempted 命令的 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 ================================
为什么不使用 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();
错误解释得很清楚:
target of an invocation. That is the
Members
function
System.ArgumentException: Value does not fall within the expected range This most probably refers to the
null
value.
我找出问题所在。 由于使用 third-party 产品准备其活动目录以获得支持,问题环境在其 AD 环境中进行了自定义。作为集成的一部分,它 运行 架构更新,将“成员”属性添加到他们的 AD 架构中。 当我们在目录条目上调用成员时,这会导致冲突。