在DirectorySearcher.FindAll()方法中的foreach循环

时间:2014-09-03 01:21:34

标签: c# asp.net directoryservices adsi

我需要在foreach中运行DirectorySearcher.FindAll()循环并获取displayname属性。似乎存在内存问题(引用链接:Memory Leak when using DirectorySearcher.FindAll())。 我的代码如下:

List<string> usersList = new List<string>();
        string displayName = string.Empty;
        try
        {
            using (DirectoryEntry directoryEntry = new DirectoryEntry(ldap, userName, password))
            {
                DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry);
                directorySearcher.PageSize = 500;  // ADD THIS LINE HERE !
                string strFilter = "(&(objectCategory=User))";
                directorySearcher.PropertiesToLoad.Add("displayname");//first name
                directorySearcher.Filter = strFilter;
                directorySearcher.CacheResults = false;
                SearchResult result;
                var resultOne = directorySearcher.FindOne();

                using (var resultCol = directorySearcher.FindAll())
                {
                    for (int counter = 0; counter < resultCol.Count; counter++)
                    {
                        result = resultCol[counter];
                        if (result.Properties.Contains("displayname"))
                        {
                            displayName = (String)result.Properties["displayname"][0];
                            usersList.Add(displayName);
                        }
                    }
                } 
            }
        }

是否有任何可能的循环方式。我也试过调用Dispose()方法,但它不起作用。任何帮助都非常感谢。

2 个答案:

答案 0 :(得分:0)

如果它在托管代码中不是有效的解决方案,并且您的代码很难依赖于非托管的东西,例如Active Directory,我认为移动目录搜索逻辑以将此类逻辑与您的主要隔离是个好主意应用领域。它不会逆风而行。

对我来说 - 更好的方法是使用外部控制台进程,将参数发送到参数字符串并捕获StandardOutput。

速度会慢一些,但内存不会泄露,因为在控制台进程死后,系统会释放内存。

此外,在这种情况下,您不能制作自制的ad_searcher.ex,而是使用标准的dsquery等。例如:

[https://serverfault.com/questions/49405/command-line-to-list-users-in-a-windows-active-directory-group]

另一种方法 - 使用托管子域名,但我认为它更难,而且我不确定是否会释放所有非托管资源。

答案 1 :(得分:0)

这是我为我正在研究的项目提出的解决方案,我认为这对您有用。我的解决方案遍历搜索结果,并在最多20个字符串列表中返回显示名称。

using (DirectorySearcher ds = new DirectorySearcher())
        {
            //My original filter
            //ds.Filter = string.Format("(|(&(objectClass=group)(|(samaccountname=*{0}*)(displayname=*{0}*)))(&(objectCategory=person)(objectClass=user)(|(samaccountname=*{0}*)(displayname=*{0}*))))", name);

            //Your Modified filter                
            ds.filter = "(objectCategory=User)"


            ds.PropertiesToLoad.Add("displayname");

            ds.SizeLimit = 20;

            SearchResultCollection result = ds.FindAll();

            List<string> names = new List<string>();

            foreach (SearchResult r in result)
            {
                var n = r.Properties["displayname"][0].ToString();
                if (!names.Contains(n))
                    names.Add(n);
            }

            return Json(names, JsonRequestBehavior.AllowGet);
        }