цикл foreach в методе DirectorySearcher.FindAll()

Мне нужно запустить цикл foreach в DirectorySearcher.FindAll() и получить свойство displayname. Похоже, что с этим возникают проблемы с памятью (ссылка: утечка памяти при использовании 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(), но он не работает. Любая помощь очень ценится.


person Shanky    schedule 03.09.2014    source источник


Ответы (2)


Вот решение, которое я придумал для проекта, над которым я работаю, и которое, я думаю, подойдет вам. Мое решение перебирает результаты поиска и возвращает отображаемое имя в списке строк до 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);
        }
person armstb01    schedule 17.04.2018

Если это недопустимое решение в управляемом коде, и ваш код сильно зависит от неуправляемых вещей, таких как Active Directory, я думаю, что было бы неплохо переместить логику поиска в каталоге, чтобы изолировать такую ​​логику от вашего основного домена приложения. Это способ не бежать против ветра.

Для меня лучше использовать внешний консольный процесс, отправить параметры в строку аргумента и поймать StandardOutput.

Это будет медленнее, но память не будет утекать, потому что она будет освобождена системой после смерти консольного процесса.

Дополнительно в этом случае можно не делать самодельный ad_searcher.ex, а использовать стандартный dsquery и т.д. Например:

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

Другой подход - использование управляемых поддоменов, НО я думаю, что это сложнее, и я не уверен, что все неуправляемые ресурсы будут освобождены.

person comdiv    schedule 03.09.2014
comment
Команда в ссылке предназначена для локальной системы, тогда как у меня есть AD на сервере (LDAP). Любой способ получить это? - person Shanky; 03.09.2014
comment
Как я уже сказал выше, вы можете использовать свой собственный код, но переместить его в изолированные процессы (исполнительная консоль с простым выводом), но dsquery, похоже, полезен во всех местах. Не должно быть большой разницы, где именно размещается AD для запроса с любого хоста, который является членом AD (я не хорошо сформированный администратор, но, похоже, это ядро ​​​​идеологии AD). Полное объяснение dsquery находится здесь: technet.microsoft.com/en-us/library /cc754232.aspx - person comdiv; 03.09.2014