改进递归Active Directory功能

时间:2012-03-02 14:11:59

标签: vb.net recursion active-directory

我希望改善以下内容的性能,并返回每个用户的GUID。

我已经转换并修改code found here以递归搜索组以获取所有成员及其详细信息,并将它们添加到类集合中。但是我还需要捕获用户的管理器详细信息,因此我为每个用户调用AD两次。这似乎并不高效,因为许多用户将拥有相同的经理。从集合类中获取不同的管理器详细信息并仅调用它们,然后在集合中出现的任何位置替换它们似乎是合乎逻辑的。我不知道这样做的最佳方式 - 对所有这些仍然相当新;)

我也希望能够获得用户的GUID,我尝试直接将其作为集合的属性访问,但它不会返回任何内容。

这是我的代码,我真的很感激任何意见/建议:) - 或者我一般指出的任何坏习惯! ;)

我正在使用vs2005和.Net 2.0

Public Class ADCLass
        ''' <summary>
        ''' Calls recursive function to return users in group
        ''' </summary>
        ''' <param name="DistListAlias">CN for the Group</param>
        ''' <returns>Collection of class holding user details</returns>
        ''' <remarks></remarks>
        Public Function GetDistListUsers(ByVal DistListAlias As String) As Collection(Of ADMembers)
            Dim path As String = "LDAP://DC=systems,DC=Private"
            Dim filter As String
            Dim filterFormat As String = "(cn={0})"
            Dim sAMAccountFilter As String

            filter = String.Format(filterFormat, DistListAlias)

            Dim properties As PropertyCollection = GetPropertiesForEntry(path, filter)

            sAMAccountFilter = "(|(ObjectClass=Group)(objectCategory=user))"
            Dim groupMembers As Collection(Of ADMembers) = New Collection(Of ADMembers)

            If Not IsNothing(properties) Then

                Dim sAMAccountTypes As Collection(Of Integer) = New Collection(Of Integer)
                groupMembers = GetUsersInGroup(properties, groupMembers, sAMAccountFilter)

            End If
            Return groupMembers
        End Function

#Region "GetUsersInGroup"
        ''' <summary>
        ''' Recursive function to list all users in group and sub group
        ''' Returns the sAMAccountName for the Managers
        ''' </summary>
        ''' <param name="Properties">Group Properties</param>
        ''' <param name="groupMembers">Collection fo Users</param>
        ''' <param name="filter"></param>
        ''' <returns>Collection of class holding user details</returns>
        ''' <remarks></remarks>
        Private Function GetUsersInGroup(ByVal Properties As PropertyCollection, ByVal groupMembers As Collection(Of ADMembers), ByVal filter As String)
            Dim pathFormat As String = "LDAP://{0}"
            Dim memberIdx As String = "member"
            Dim sAMAccountNameIdx As String = "sAMAccountName"
            Dim sAMAccountTypeIdx As String = "sAMAccountType"
            Dim personnelNumberIdx As String = "extensionAttribute4"
            Dim TelNo As String
            Dim prop As Object
            Dim managerID As String
            Dim manColl As PropertyCollection

            If Not IsNothing(Properties(memberIdx)) Then
                'Loop through found Members
                For Each prop In Properties(memberIdx)

                    Dim distinguishedName As String = prop.ToString
                    Dim path As String = String.Format(pathFormat, distinguishedName)
                    Dim childProperties As PropertyCollection = GetPropertiesForEntry(path, filter)

                    If Not IsNothing(childProperties) Then
                        'Check that this is a user
                        If childProperties(sAMAccountTypeIdx).Value = 805306368 Then

                            'GetManager ID
                            managerID = childProperties("manager").Value.ToString
                            manColl = GetPropertiesForEntry(String.Format(pathFormat, managerID), filter)
                            managerID = manColl(sAMAccountNameIdx).Value.ToString

                            'Get Phone Number, if telephone number is null, check mobile, if null
                            'return ""
                            If Not IsNothing(childProperties("telephoneNumber").Value) Then
                                TelNo = childProperties("telephoneNumber").Value.ToString
                            Else
                                If Not IsNothing(childProperties("mobile").Value) Then
                                    TelNo = childProperties("mobile").Value.ToString
                                Else
                                    TelNo = ""
                                End If
                            End If
                            'Add the Properties to the class collection
                            groupMembers.Add(New ADMembers(childProperties(sAMAccountNameIdx).Value.ToString, _
                                                    childProperties("cn").Value.ToString, _
                                                    managerID, _
                                                    childProperties("Title").Value.ToString, _
                                                    TelNo, _
                                                    childProperties("mail").Value.ToString))
                        Else
                            'Found a group - recurse
                            GetUsersInGroup(childProperties, groupMembers, filter)
                        End If
                    End If
                Next

            End If
            Return groupMembers
        End Function


#End Region
#Region "GetPropertiesForEntry"
        ''' <summary>
        ''' Gets properties for given user in AD
        ''' </summary>
        ''' <param name="path">Distinguished AD name</param>
        ''' <param name="filter"></param>
        ''' <returns>Property collection for given user</returns>
        ''' <remarks></remarks>
        Private Function GetPropertiesForEntry(ByVal path As String, ByVal filter As String) As PropertyCollection

            Dim rootEntry As New DirectoryEntry(path)
            Dim searcher As New DirectorySearcher(rootEntry)

            With searcher
                .Filter = filter
                .PageSize = 5
                .ServerTimeLimit = New TimeSpan(0, 0, 30)
                .ClientTimeout = New TimeSpan(0, 10, 0)
            End With

            Dim result As SearchResult = searcher.FindOne

            Return result.GetDirectoryEntry.Properties

        End Function
#End Region

    End Class

我根据JPBlancs的建议使用的代码,虽然这有效,但它比我原来慢得多,我实施它是不是很复杂?

Public Sub GetPropertiesForEntry()

    Dim rootEntry As New DirectoryEntry("LDAP://DC=d1,DC=d2")
    Dim searcher As New DirectorySearcher(rootEntry)

    With searcher
        .Filter = "(&(memberof:1.2.840.113556.1.4.1941:=CN=grp1,OU=Messaging Groups,OU=Groups,DC=d1,DC=d2)(objectCategory=user))"
        .SearchScope = SearchScope.Subtree
        .PropertiesToLoad.Add("cn")
        .PageSize = 100
        .ServerTimeLimit = New TimeSpan(0, 0, 30)
        .ClientTimeout = New TimeSpan(0, 10, 0)
    End With

    Dim results As SearchResultCollection = searcher.FindAll()
    For Each result As SearchResult In results
        Debug.Print(result.Properties("cn").Item(0).ToString)
    Next
End Sub

1 个答案:

答案 0 :(得分:1)

你能看看Finding users that are members of two active directory groups吗?您将找到一种方法,使用LDAP_MATCHING_RULE_IN_CHAIN在一个查询中从组中收集递归用户。

就GUID而言,不要忘记列出要查询返回的属性。小心,据我所知,GUID将在INT数组中返回。

dsLookFor.PropertiesToLoad.Add("objectGUID")