I hope to improve the performance below, and also return a GUID for each user.
I converted and modified the code found here to search for groups recursively to get all members and their data and add them to the collection class. However, I also need to collect data about user managers, so I call AD twice for each user. This does not seem effective, as many users will have the same manager. It would seem logical to get individual manager data from the collection class and call only these, and then replace them wherever they appear in the collection. I don't know how best to do this, but still pretty new to all of this;)
I would also like to get the user's GUID, I tried accessing it directly as a collection property, but returns nothing.
Here is my code, I would really appreciate any comments / suggestions :) - or any bad habits that I have at all, indicating !;)
I am using vs2005 and .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
''' <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
''' <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
The code I use according to the JPBlancs suggestion while it works, is it much slower than my original, am I implementing it unreclty?
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