Vb.net 改进递归Active Directory函数

Vb.net 改进递归Active Directory函数,vb.net,recursion,active-directory,Vb.net,Recursion,Active Directory,我希望提高下面的性能,并返回每个用户的GUID 我已经转换并修改了用于递归搜索组的,以获取所有成员及其详细信息,并将它们添加到类集合中。但是,我还需要捕获用户经理的详细信息,因此我会为每个用户打两次广告。这似乎效率不高,因为许多用户将使用相同的管理器。从集合类中获取不同的管理器细节并仅调用这些细节,然后在集合中出现的任何地方替换它们,这似乎是合乎逻辑的。但是,我不知道最好的方法是什么——对这一切还是相当陌生的;) 我还希望能够获取用户的GUID,我尝试将其作为集合的属性直接访问,但它不返回任何内

我希望提高下面的性能,并返回每个用户的GUID

我已经转换并修改了用于递归搜索组的,以获取所有成员及其详细信息,并将它们添加到类集合中。但是,我还需要捕获用户经理的详细信息,因此我会为每个用户打两次广告。这似乎效率不高,因为许多用户将使用相同的管理器。从集合类中获取不同的管理器细节并仅调用这些细节,然后在集合中出现的任何地方替换它们,这似乎是合乎逻辑的。但是,我不知道最好的方法是什么——对这一切还是相当陌生的;)

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

这是我的代码,我非常感谢您的任何评论/建议:)-或者我通常指出的任何坏习惯!;)

我正在使用vs2005和.NET2.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
你能看一下吗。您将发现一个方法,用于在一个查询中递归地从组中收集用户

就GUID而言,不要忘记列出希望查询返回的属性。小心,据我记忆所及,GUID将以INT数组返回

dsLookFor.PropertiesToLoad.Add("objectGUID")

谢谢JPBlanc,这真的很有用,所以如果我做对了,我可以使用它返回所有用户,其中的组可能不直接在该组中,但在任意数量的嵌套子组中?很抱歉,如果这听起来很明显,但我仍然是非常新的在这方面!!感谢您的回答JPBlanc,除非我没有正确地实现这一点(很可能;)我已经在上面发布了我的代码,你介意快速查看一下,看看我是否做了任何明显错误的事情吗?这不是我第一次听说这个请求很慢。首先,你得到了好的答案吗?你得到了多少回应?第二,您可以使用(objectCategory=person)进行相同的测试,甚至删除此部分。总共返回了大约180个用户,在主列表中有大约8或9个嵌套组(通讯组列表)需要从中获取。我得到了正确的答案,与原始代码完全一样:),我会给ObjtCype一个Go,谢谢你的帮助+1我仍然使用我的原始代码,但是它只需要每天在半夜运行一次,所以现在的性能并不那么重要。您的解决方案很有效,我非常感谢您的帮助,当然可以简化工作:)
dsLookFor.PropertiesToLoad.Add("objectGUID")