.net ActiveDs.IADsMembers-枚举包含外部安全主体的全局组

.net ActiveDs.IADsMembers-枚举包含外部安全主体的全局组,.net,active-directory,.net,Active Directory,我正在使用以下命令枚举Active Directory中的域本地组: Dim de As New DirectoryEntry("path") Dim members As IADsMembers = DirectCast(de.Invoke("Members"), IADsMembers) members.Filter = New Object() {"user"} 'Iterate over users. members.Filter = New Object() {"group"} 'I

我正在使用以下命令枚举Active Directory中的域本地组:

Dim de As New DirectoryEntry("path")
Dim members As IADsMembers = DirectCast(de.Invoke("Members"), IADsMembers)

members.Filter = New Object() {"user"}
'Iterate over users.
members.Filter = New Object() {"group"}
'Iterate over nested groups.
域本地组未枚举。我已经检查了
成员。Count
等于1

查看Active Directory后,有一个外部安全主体链接到另一个域中的全局组。研究表明,
成员.过滤器的唯一选项是
用户和组
用户


如何从该集合中提取外部安全主体?

您的域中存在
外部安全主体这一事实表明您的组成员实际上来自另一个林。您需要确保用于运行代码的帐户具有访问其他林的权限

如果您使用的是.NET 3.5或更高版本,则应尝试使用


我想我应该解决你的问题。这包括如何使用此
GroupPrincipal
的示例。它允许您指定是否递归获取成员。它还提到您可以从不同的林中获取成员。

您的域中有
外部安全主体
,这表明您的组成员实际上来自另一个林。您需要确保用于运行代码的帐户具有访问其他林的权限

如果您使用的是.NET 3.5或更高版本,则应尝试使用


我想我应该解决你的问题。这包括如何使用此
GroupPrincipal
的示例。它允许您指定是否递归获取成员。它还提到,您可以从不同的林中获取成员。

在大多数情况下,我选择使用.NET 3.5中的
System.Directory.AccountManagement
提供的功能来枚举全局组。如果要枚举的对象实际上是一个外部安全主体,那么.NET 3.5代码就不够了。希望以下代码能帮助其他人:

Private Sub EnumerateGlobalGroup(ByVal distinguishedName As String)

    Try

        Using context As New PrincipalContext(ContextType.Domain, GetDomainName(distinguishedName))
            Using gp As GroupPrincipal = GroupPrincipal.FindByIdentity(context, IdentityType.DistinguishedName, distinguishedName)
                Dim groupMembers As PrincipalSearchResult(Of Principal) = gp.GetMembers(True)
                For Each member As Principal In groupMembers

                    Console.WriteLine(member.DisplayName)
                    Select Case member.StructuralObjectClass
                        Case "user"
                            Console.WriteLine("user")
                        Case "group"
                            Console.WriteLine("group")
                    End Select

                Next
            End Using
        End Using

    Catch ex As Exception

        If Not TypeOf ex Is PrincipalOperationException Then Throw ex

        'Get this far then enumerating Foreign Security Principal.
        Dim groupEntry As New DirectoryEntry("LDAP://" & distinguishedName)
        Dim members As Object = groupEntry.Invoke("Members")
        For Each member As Object In CType(members, IEnumerable)
            Dim memberEntry As New DirectoryEntry(member)
            Console.WriteLine(memberEntry.Name)

            Dim sid As New SecurityIdentifier(DirectCast(memberEntry.InvokeGet("objectSid"), Byte()), 0)
            Dim account As NTAccount = sid.Translate(GetType(NTAccount))
            Console.WriteLine(account.ToString)

            Dim memberDistinguishedName As String = GetDistinguishedName(account.ToString)
            EnumerateGlobalGroup(memberDistinguishedName)
        Next

    End Try

End Sub

Private Function GetDomainName(ByVal dn As String) As String

    Dim dnParts As String() = dn.Split(Char.Parse(","))
    For Each d As String In dnParts
        If d.StartsWith("DC") Then Return d.ToUpper().Replace("DC=", Nothing)
    Next
    Return Nothing

End Function

Private Function GetDistinguishedName(ByVal accountName As String) As String

    Dim nameTranslate = New ActiveDs.NameTranslate()
    nameTranslate.Set(ActiveDs.ADS_NAME_TYPE_ENUM.ADS_NAME_TYPE_NT4, accountName)

    Return nameTranslate.Get(ActiveDs.ADS_NAME_TYPE_ENUM.ADS_NAME_TYPE_1779)

End Function

可能有更好的方法来实现这一点,但是它很有效。在大多数情况下,我选择使用.NET 3.5中的
System.Directory.AccountManagement
提供的功能来枚举全局组。如果要枚举的对象实际上是一个外部安全主体,那么.NET 3.5代码就不够了。希望以下代码能帮助其他人:

Private Sub EnumerateGlobalGroup(ByVal distinguishedName As String)

    Try

        Using context As New PrincipalContext(ContextType.Domain, GetDomainName(distinguishedName))
            Using gp As GroupPrincipal = GroupPrincipal.FindByIdentity(context, IdentityType.DistinguishedName, distinguishedName)
                Dim groupMembers As PrincipalSearchResult(Of Principal) = gp.GetMembers(True)
                For Each member As Principal In groupMembers

                    Console.WriteLine(member.DisplayName)
                    Select Case member.StructuralObjectClass
                        Case "user"
                            Console.WriteLine("user")
                        Case "group"
                            Console.WriteLine("group")
                    End Select

                Next
            End Using
        End Using

    Catch ex As Exception

        If Not TypeOf ex Is PrincipalOperationException Then Throw ex

        'Get this far then enumerating Foreign Security Principal.
        Dim groupEntry As New DirectoryEntry("LDAP://" & distinguishedName)
        Dim members As Object = groupEntry.Invoke("Members")
        For Each member As Object In CType(members, IEnumerable)
            Dim memberEntry As New DirectoryEntry(member)
            Console.WriteLine(memberEntry.Name)

            Dim sid As New SecurityIdentifier(DirectCast(memberEntry.InvokeGet("objectSid"), Byte()), 0)
            Dim account As NTAccount = sid.Translate(GetType(NTAccount))
            Console.WriteLine(account.ToString)

            Dim memberDistinguishedName As String = GetDistinguishedName(account.ToString)
            EnumerateGlobalGroup(memberDistinguishedName)
        Next

    End Try

End Sub

Private Function GetDomainName(ByVal dn As String) As String

    Dim dnParts As String() = dn.Split(Char.Parse(","))
    For Each d As String In dnParts
        If d.StartsWith("DC") Then Return d.ToUpper().Replace("DC=", Nothing)
    Next
    Return Nothing

End Function

Private Function GetDistinguishedName(ByVal accountName As String) As String

    Dim nameTranslate = New ActiveDs.NameTranslate()
    nameTranslate.Set(ActiveDs.ADS_NAME_TYPE_ENUM.ADS_NAME_TYPE_NT4, accountName)

    Return nameTranslate.Get(ActiveDs.ADS_NAME_TYPE_ENUM.ADS_NAME_TYPE_1779)

End Function

可能有更好的方法来实现这一点,但是它很有效

我很兴奋能在.NET3.5中使用这些我忘记了的漂亮包装。如果全局组包含一个FSP,FindByIdentity就会失败。我对在.NET3.5中使用所有这些漂亮的包装器感到非常兴奋,我忘记了这些。如果全局组包含FSP,则FindByIdentity将失败。