• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1248
  • Last Modified:

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
0
IUFITS
Asked:
IUFITS
  • 2
  • 2
2 Solutions
 
UnifiedISCommented:
use object.finalize on your AD objects to spur reclamation of memory resources.
0
 
IUFITSAuthor Commented:
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
0
 
UnifiedISCommented:
I'm guessing your leak is from the AD objects, not your .net code.  .Net will not know how to clean up whatever the AD objects did outside of .net while they existed.  I think you'll want to create a finalize method in your class.  I'm not well-versed on finalize but it's my understanding that it helps clean up unmanaged objects.  
0
 
IUFITSAuthor Commented:
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.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now