Deeeyewhy
Deeeyewhy

Reputation: 19

Memory leak in DirectorySearcher loop

I am using DirectorySearcher in a using statement to loop through about 5000 objects. It appears through troubleshooting that the PropertiesToLoad property is causing a massive memory leak. My program goes from 0 to 2 GB of memory used in no time flat if I set the propertiesToLoad property on each object. In this manner the search is very fast but has the memory leak.

If I set the PropertiesToLoad at the beginning and not on each loop the memory leak does not occur but the search is slow. I have tried clearing the Properties on each loop which fixes the memory leak but again causes the search to slowdown. I am hoping to find the best of both worlds here.

NOTE: My app is Multi-Threaded so the AD search is happening on 10 threads at once.

using (DirectorySearcher mySearcher = new DirectorySearcher(new DirectoryEntry("LDAP://rootDSE", null, null, AuthenticationTypes.FastBind)))
            { 
                        try
                        {
                            mySearcher.Filter = ("(&(objectClass=user)(sAMAccountName=" + object + "))");
                            mySearcher.SearchScope = SearchScope.Subtree;
                            mySearcher.CacheResults = false;
                            mySearcher.PropertiesToLoad.AddRange(new string[] { "canonicalName", "displayName", "userAccountControl" });

                            foreach (SearchResult result in mySearcher.FindAll())
                            {
                                try
                                {
                                    shareInfo.displayname = result.Properties["displayName"][0].ToString();
                                }
                                catch
                                {
                                    shareInfo.displayname = "N/A";
                                }

                                shareInfo.canName = result.Properties["canonicalName"][0].ToString();

                                int userAccountControl = Convert.ToInt32(result.Properties["userAccountControl"][0]);
                                bool disabled = ((userAccountControl & 2) > 0);
                                if (disabled == true)
                                    shareInfo.acctstatus = "Disabled";
                                else
                                    shareInfo.acctstatus = "Enabled";
                            }
                        }
                        catch
                        {

                        }
            }  

Upvotes: 0

Views: 537

Answers (1)

Gabriel Luci
Gabriel Luci

Reputation: 40998

Here's something I learned just a few weeks ago from the documentation for the FindAll method:

Due to implementation restrictions, the SearchResultCollection class cannot release all of its unmanaged resources when it is garbage collected. To prevent a memory leak, you must call the Dispose method when the SearchResultCollection object is no longer needed.

You're using using on the DirectorySearcher, but not on the result collection. Try assigning the resulting collection to a variable that can be disposed later:

using (var results = mySearcher.FindAll())
{
    foreach (SearchResult result in results)
    {
        ...
    }
}

Upvotes: 4

Related Questions