Looping through Active Directory to get managers and direct reports

筅森魡賤 提交于 2020-01-05 08:03:29

问题


Go easy on me, this is my first question ;)

I've spent a lot of time looking, but I haven't found what I'm looking for. I've got an intranet based reporting tool (VB.Net + ASP.Net Integrated Windows Authentication) that looks up users and managers from a SQL Server 2005 table to roll up the reporting to manager level.

This table is currently manually maintained and I've been asked to make it more dynamic as it is going to be up-scaled for far more users. Therefore I'm looking to link in with the Active Directory to create an Org table in the back end which will replace the current manually entered one.

I'm comfortable getting user data from the AD, but not so sure as to the best approach to set this up, I was thinking of the following table:

CREATE TABLE dbo.Employees
(
    EmpID       nvarchar(8) PRIMARY KEY,
    EmpName     nvarchar(30),
    EmpNo       nvarchar(15),
    EmpEmail    nvarChar(255),
    EmpTitle    nvarchar(255),
    MgrID       nvarchar(8) FOREIGN KEY REFERENCES Employees(EmpID)
)
GO

EmpID will be the NetworkID (sAMAccountName).

Then this will need populating from the AD, I'm guessing through recursive calls to fill in the fields.

I'm then not sure how to structure the code so that it will capture every employee under every manager starting at a given level.

I'm currently using the below to capture the direct reports for a given manager:

 Public Function GetDirectReports(ByVal ADFullName As String) As ArrayList

            Dim adItems As ArrayList = New ArrayList

            Dim rootEntry As New DirectoryEntry("LDAP://" & ADFullName)

            Dim searcher As New DirectorySearcher(rootEntry)
            searcher.PropertiesToLoad.Add("directReports")
            searcher.PropertiesToLoad.Add("sAMAccountName")
            searcher.PropertiesToLoad.Add("cn")

            searcher.PageSize = 5
            searcher.ServerTimeLimit = New TimeSpan(0, 0, 30)
            searcher.ClientTimeout = New TimeSpan(0, 10, 0)

            Dim queryResults As SearchResultCollection
            queryResults = searcher.FindAll()

            Dim x As Integer

            For Each result As SearchResult In queryResults
                For x = 0 To result.Properties("directReports").Count - 1
                    adItems.Add(New ADReports(result.Properties("directReports")(x), _
                                ExtractUser(result.Properties("directReports")(x))))
                Next
            Next
            Return adItems
        End Function

        Private Function ExtractUser(ByVal username) As String
            Return Split(Split(username, "CN=")(1), ",")(0)
        End Function

Any comments suggestions and help would be very much appreciated :)


回答1:


Basically what I would do is simply recurse through the entire AD and grab out all the users, with the relevant info needed, and store them in SQL Server. While enumerating, don't worry and care about the hierarchies - you'll handle those later.

Once the data is inside SQL Server, you could then create e.g. a recursive CTE (Common Table Expression) to get the hierarchy of the employees - who reports to whom etc.

As a side-note: the sAMAccountName is not guaranteed to stay stable - it could change (rare, but possible) - so maybe you need another item as the unique identifier for each user? Does your company use the userID attribute, or something else? Or could you use the AD user GUID (which will stay the same forever) instead of the samAccountName?

Also: if you choose to stick with the sAMAccountName: be aware it could be up to 20 characters long - NVARCHAR(8) won't be enough. Also: do you really need the Unicode strings? Those are just always twice as long as the non-Unicode VARCHAR(20) strings - just asking, you might need it, then that's fine.

I would probably add an artificial EmployeeID (INT IDENTITY) column to the table to handle all the requirements for a good clustering key on that table: unique, stable, narrow. A nvarchar(20) is first of all variable length which isn't terribly good, and it could be up to 40 bytes long - which again is not optimal.




回答2:


You can use this code snippet to get manager name for certain employee. If you want to know subordinates of manager, then please replace directreports with manager.

    lblUser.Text = My.User.Name
    Dim _UserName As String = GetDomainUserName(My.User.Name)
    Dim context As PrincipalContext = New PrincipalContext(ContextType.Domain)


    ' find a user
    Dim user As UserPrincipal = UserPrincipal.FindByIdentity(context, lblUser.Text)

    Dim allUsers As New ArrayList()
    Dim searchRoot As New DirectoryEntry("LDAP://DOMAIN")
    Dim search As New DirectorySearcher(searchRoot)
    'search.Filter = "(&(objectClass=user)(manager=" + user.DistinguishedName + "))"
    search.Filter = "(&(objectClass=user)(directReports=" + user.DistinguishedName + "))"
    search.PropertiesToLoad.Add("samaccountname")

    Dim result As SearchResult
    Dim resultCol As SearchResultCollection = search.FindAll()
    If resultCol IsNot Nothing Then
        For counter As Integer = 0 To resultCol.Count - 1
            result = resultCol(counter)
            If result.Properties.Contains("samaccountname") Then
                allUsers.Add(DirectCast(result.Properties("samaccountname")(0), [String]))
            End If
        Next
    End If


来源:https://stackoverflow.com/questions/9498908/looping-through-active-directory-to-get-managers-and-direct-reports

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!