Список всех компьютеров в активном каталоге
Мне интересно, как получить список всех компьютеров/компьютеров/ПК из активного каталога?
(Пытаясь сделать эту страницу приманкой для поисковой системы, ответит сам. Если у кого-то есть лучший ответ, я соглашусь с этим)
Ответы
Ответ 1
Если у вас очень большой домен, или у вашего домена установлены ограничения на то, как количество элементов может быть возвращено для каждого поиска, вам, возможно, придется использовать пейджинг.
using System.DirectoryServices; //add to references
public static List<string> GetComputers()
{
List<string> ComputerNames = new List<string>();
DirectoryEntry entry = new DirectoryEntry("LDAP://YourActiveDirectoryDomain.no");
DirectorySearcher mySearcher = new DirectorySearcher(entry);
mySearcher.Filter = ("(objectClass=computer)");
mySearcher.SizeLimit = int.MaxValue;
mySearcher.PageSize = int.MaxValue;
foreach(SearchResult resEnt in mySearcher.FindAll())
{
//"CN=SGSVG007DC"
string ComputerName = resEnt.GetDirectoryEntry().Name;
if (ComputerName.StartsWith("CN="))
ComputerName = ComputerName.Remove(0,"CN=".Length);
ComputerNames.Add(ComputerName);
}
mySearcher.Dispose();
entry.Dispose();
return ComputerNames;
}
Ответ 2
Что предлагает EKS, правильный, но выполняет немного медленно.
Причиной этого является вызов GetDirectoryEntry()
для каждого результата. Это создает объект DirectoryEntry
, который необходим только в том случае, если вам нужно изменить объект активной директории (AD). Это нормально, если ваш запрос возвратит один объект, но при перечислении всего объекта в AD это значительно ухудшает производительность.
Если вам нужно запросить только AD, лучше всего использовать коллекцию Properties
объекта результата. Это несколько раз улучшит производительность кода.
Это объясняется в документации для SearchResult
класса:
Экземпляры класса SearchResult
очень похожи на экземпляры DirectoryEntry
. Существенное различие заключается в том, что DirectoryEntry
класс извлекает информацию из Active Иерархии доменных имен каталогов каждый раз, когда новый объект доступа, тогда как данные для SearchResult
уже доступны в SearchResultCollection
, где он возвращается из запроса, который выполняется с классом DirectorySearcher
.
Вот пример о том, как использовать коллекцию Properties
:
public static List<string> GetComputers()
{
List<string> computerNames = new List<string>();
using (DirectoryEntry entry = new DirectoryEntry("LDAP://YourActiveDirectoryDomain.no")) {
using (DirectorySearcher mySearcher = new DirectorySearcher(entry)) {
mySearcher.Filter = ("(objectClass=computer)");
// No size limit, reads all objects
mySearcher.SizeLimit = 0;
// Read data in pages of 250 objects. Make sure this value is below the limit configured in your AD domain (if there is a limit)
mySearcher.PageSize = 250;
// Let searcher know which properties are going to be used, and only load those
mySearcher.PropertiesToLoad.Add("name");
foreach(SearchResult resEnt in mySearcher.FindAll())
{
// Note: Properties can contain multiple values.
if (resEnt.Properties["name"].Count > 0)
{
string computerName = (string)resEnt.Properties["name"][0];
computerNames.Add(computerName);
}
}
}
}
return computerNames;
}
Документация для SearchResult.Properties
Обратите внимание, что свойства могут иметь несколько значений, поэтому мы используем Properties["name"].Count
для проверки количества значений.
Чтобы улучшить ситуацию еще больше, используйте коллекцию PropertiesToLoad
, чтобы поисковик знал, какие свойства вы собираетесь использовать заранее. Это позволяет поисковику считывать только данные, которые будут использоваться.
Обратите внимание, что объекты DirectoryEntry
и DirectorySearcher
должны быть надлежащим образом размещены, чтобы освободить все используемые ресурсы. Это лучшее выполняется с помощью предложения using
.
Ответ 3
Запрос LDAP, например: (objectCategory = computer), должен сделать трюк.
-Джим