【问题标题】:foreach loop in DirectorySearcher.FindAll() methodDirectorySearcher.FindAll() 方法中的 foreach 循环
【发布时间】:2014-09-03 01:21:33
【问题描述】:

我需要在DirectorySearcher.FindAll() 中运行foreach 循环并获取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() 方法,但它不起作用。非常感谢任何帮助。

【问题讨论】:

    标签: c# asp.net directoryservices adsi


    【解决方案1】:

    这是我为我正在从事的一个项目提出的一个解决方案,我认为它对你有用。我的解决方案遍历搜索结果并在最多 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);
            }
    

    【讨论】:

      【解决方案2】:

      如果它不是托管代码中的有效解决方案,并且您的代码严重依赖于非托管事物,例如 Active Directory,我认为移动目录搜索逻辑以将此类逻辑与您的主应用程序域隔离是个好主意。这是不逆风奔跑的方式。

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

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

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

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

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

      【讨论】:

      • 链接中的命令适用于本地系统,而我的 AD 在服务器 (LDAP) 上。有什么办法吗?
      • 正如我上面所说的 - 您可以使用您的自定义代码,但将其移动到隔离进程(具有简单输出的单例控制台执行程序),但 dsquery 似乎在所有位置都有用。确切地放置AD以从AD成员的任何主机查询它一定没有太大区别(我不是很好的管理员,但它似乎是AD意识形态的核心)。 dsquery 的完整解释在这里:technet.microsoft.com/en-us/library/cc754232.aspx
      猜你喜欢
      • 1970-01-01
      • 2021-05-28
      • 1970-01-01
      • 2016-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多