【问题标题】:Improving recursive Active Directory function改进递归 Active Directory 功能
【发布时间】:2012-03-02 14:11:58
【问题描述】:

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

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

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

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

我正在使用 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

【问题讨论】:

    标签: vb.net recursion active-directory


    【解决方案1】:

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

    就 GUID 而言,不要忘记列出您希望查询返回的属性。小心,据我记得 GUID 将返回一个 INT 数组。

    dsLookFor.PropertiesToLoad.Add("objectGUID")
    

    【讨论】:

    • 感谢 JPBlanc,这真的很有用,所以如果我有这个权利,我可以用它来返回所有用户,这些用户可能不是直接在该组中,而是在任意数量的嵌套子组中?对不起,如果这听起来很明显,但我还是很新!
    • 感谢您的回答 JPBlanc,但是除非我没有正确实现这一点(很有可能;)!!)我已经在上面发布了我的代码,您介意快速查看一下我是否是做了什么明显错误的事情?
    • 我不是第一次听说这个请求很慢。首先你得到好的答案吗?你抓住了多少回应?其次,您可以使用 (objectCategory=person) 甚至删除这部分进行相同的测试。
    • 总共返回了大约 180 个用户,它必须从主列表中获取大约 8 或 9 个嵌套组(分发列表)。我得到了正确的答案,与原始代码完全相同:),我会试试 objectcategory,感谢您的帮助 +1
    • 我仍在使用我的原始代码,但它只需要每天半夜运行一次,所以现在性能不是那么重要。您的解决方案有效,我很感谢您的所有帮助,并且肯定会简化事情:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-09
    • 1970-01-01
    相关资源
    最近更新 更多