Link to home
Start Free TrialLog in
Avatar of IUFITS
IUFITS

asked on

DirectoryServices memory leak

I appear to be leaking memory with the below function.  I was looking for the fastest ways to add a list of users into an AD group.  Querying the user each time for existence and then doing a mass committ turned out to be as slow as doing them one by one for some reason.  Anyway, I believe I'm disposing of everything but the program adds about 1-2 meg of RAM usage every second or two of usage while it's looping through a userlist adding records... what am I missing?

        ''' <summary>  
        '''   <para>
        ''' Adds a user to a specied ADS group.  The Username and Password properties will need to be set to an account
        ''' that has permissions to add to this group.
        '''   </para>  
        ''' </summary>  
        Public Sub AddAdsUserToGroup(ByVal UsernameToAdd As String, ByVal GroupToAddTo As String)
            Dim Buf As String = ""
            Dim adUserFolder As DirectoryEntry = New DirectoryEntry(_ldapDomain & "/DC=ads,DC=iu,DC=edu")

            ' This user is an active directory user and it will need access to write to the group you're trying to add to
            adUserFolder.Username = _username
            adUserFolder.Password = _password
            Dim adSearch As New System.DirectoryServices.DirectorySearcher(adUserFolder)

            ' group1 represents the active directory group name
            adSearch.Filter = String.Format("(&(objectCategory=group)(sAMAccountName= {0}))", GroupToAddTo)

            ' There should only be one entry in this group because you listed the exact address, if it returned multiple
            ' you would be adding this user to all of those groups which could easily manifest into an issue if not used
            ' properly. I see this as a very controled script though so it shouldn't be an issue.
            For Each x As SearchResult In adSearch.FindAll
                Dim group As DirectoryEntry = x.GetDirectoryEntry

                ' Only add the user if they don't exist in the group
                If group.Properties("member").Contains("CN=" & UsernameToAdd & ",OU=Accounts,DC=ads,DC=iu,DC=edu") = False Then
                    Try
                        group.Properties("member").Add("CN=" & UsernameToAdd & ",OU=Accounts,DC=ads,DC=iu,DC=edu")                        
                        group.CommitChanges()
                    Catch ex As Exception

                    Finally
                        If Not group Is Nothing Then group.Dispose()
                    End Try
                End If
            Next

            adSearch.Dispose()
            adUserFolder.Close()
            adUserFolder.Dispose()
            adSearch = Nothing
            adUserFolder = Nothing

        End Sub
ASKER CERTIFIED SOLUTION
Avatar of UnifiedIS
UnifiedIS

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of IUFITS
IUFITS

ASKER

Here's the sub I'm using...  when you say finalize, do you mean call dispose on those objects?

        ''' <summary>  
        '''   <para>
        ''' Adds a user to a specied ADS group.  The Username and Password properties will need to be set to an account
        ''' that has permissions to add to this group.
        '''   </para>  
        ''' </summary>  
        Public Sub AddAdsUserToGroup(ByVal UsernameToAdd As String, ByVal GroupToAddTo As String)
            Dim Buf As String = ""
            Dim adUserFolder As DirectoryEntry = New DirectoryEntry(_ldapDomain & "/DC=ads,DC=**,DC=***")

            ' This user is an active directory user and it will need access to write to the group you're trying to add to
            adUserFolder.Username = _username
            adUserFolder.Password = _password
            Dim adSearch As New System.DirectoryServices.DirectorySearcher(adUserFolder)

            ' group1 represents the active directory group name
            adSearch.Filter = String.Format("(&(objectCategory=group)(sAMAccountName= {0}))", GroupToAddTo)

            For Each x As SearchResult In adSearch.FindAll
                Dim group As DirectoryEntry = x.GetDirectoryEntry

                ' Only add the user if they don't exist in the group
                If group.Properties("member").Contains("CN=" & UsernameToAdd & ",OU=Accounts,DC=ads,DC=iu,DC=edu") = False Then
                    Try
                        group.Properties("member").Add("CN=" & UsernameToAdd & ",OU=Accounts,DC=ads,DC=iu,DC=edu")                        
                        group.CommitChanges()
                    Catch ex As Exception

                    Finally
                        If Not group Is Nothing Then group.Dispose()
                    End Try
                End If
            Next

            adSearch.Dispose()
            adUserFolder.Close()
            adUserFolder.Dispose()            
            adSearch = Nothing
            adUserFolder = Nothing

        End Sub
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of IUFITS

ASKER

I changed my code and tried to dispose everything that I could that had a dispose method to no avail, still leaking 500k of memory everytime I tried to add a user to a group.  I ended up doing what I should have done in the first place which was putting them all into one transaction, but only the users who weren't already in that group (or the whole transaction would fail).  That way, it only creates one set of objects.

I have no clue what else I could call dispose on.  I might try to figure out how to setup those loops using the 'using' keyword that is suppose to auto dispose of the objects for you... perhaps one of the objects I created created another object that had a dispose method.  Anyway, you guys had the problem correct and it put me on the right path so I split the points.  I'll post back when I figure out how to dispose of everything properly (or rather, when I figure out what wasn't getting disposed on my updated code).

Sorry for the slow response also and thanks for the help.