The Folly of FindOne in 1.1.
Recently while working, myself and an co-worker discovered that there is a memory leak in the FindOne method of the DirectorySearcher class in System.DirectoryServices. The leak occurs when FindOne returns null. This is only fixed in the 2.0 Framework, and currently that isn't an option for us. However, I wrote a DirectorySearcher called SafeDirectorySearcher that eliminates this problem. It contains a method called "FindOneSafe" which should be used in place of FindOne. It uses a bit of reflection to access a private method:
public class SafeDirectorySearcher : DirectorySearcher
{
public SearchResult FindOneSafe()
{
MethodInfo methodInfo = typeof(DirectorySearcher).GetMethod("FindAll", BindingFlags.Instance | BindingFlags.NonPublic, null, CallingConventions.Any, new Type[] {typeof(bool)}, null);
SearchResultCollection results = (SearchResultCollection) methodInfo.Invoke(this, new object[] { false });
try
{
foreach (SearchResult result in results)
{
return result;
}
return null;
}
finally
{
results.Dispose();
}
}
public SafeDirectorySearcher(DirectoryEntry searchRoot) : base(searchRoot)
{
}
public SafeDirectorySearcher(string searchRoot) : base(searchRoot)
{
}
public SafeDirectorySearcher() : base()
{
}
public SafeDirectorySearcher(string filter, string[] propertiesToLoad) : base(filter, propertiesToLoad)
{
}
public SafeDirectorySearcher(DirectoryEntry searchRoot, string filter, string[] propertiesToLoad) : base(searchRoot, filter, propertiesToLoad)
{
}
public SafeDirectorySearcher(string filter, string[] propertiesToLoad, SearchScope scope) : base(filter, propertiesToLoad, scope)
{
}
public SafeDirectorySearcher(DirectoryEntry searchRoot, string filter, string[] propertiesToLoad, SearchScope scope) : base (searchRoot, filter, propertiesToLoad, scope)
{
}
[Obsolete("This method is known to have a memory leak. Use with caution!", false)]
public new SearchResult FindOne()
{
return base.FindOne();
}
}