C# 列出活动目录中的所有计算机

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1605567/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 19:18:00  来源:igfitidea点击:

List all computers in active directory

c#active-directoryldap

提问by EKS

Im wondering how to get a list of all computers / machines / pc from active directory?

我想知道如何从活动目录中获取所有计算机/机器/PC 的列表?

(Trying to make this page a search engine bait, will reply myself. If someone has a better reply il accept that )

(试图让这个页面成为搜索引擎的诱饵,我会回复自己。如果有人有更好的回复,我接受)

采纳答案by EKS

If you have a very big domain, or your domain has limits configured on how how many items can be returned per search, you might have to use paging.

如果您有一个非常大的域,或者您的域对每次搜索可以返回的项目数量进行了限制,则您可能必须使用分页。

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;
}

回答by jwilleke

An LDAP query like: (objectCategory=computer)should do the trick.

像这样的 LDAP 查询(objectCategory=computer)应该可以解决问题。

回答by quasoft

What EKS suggested is correct, but is performing a little bit slow.

EKS 建议是正确的,但执行速度有点

The reason for that is the call to GetDirectoryEntry()on each result. This creates a DirectoryEntryobject, which is only needed if you need to modify the active directory (AD) object. It's OK if your query would return a single object, but when listing all object in AD, this greatly degrades performance.

这样做的原因是GetDirectoryEntry()对每个结果的调用。这将创建一个DirectoryEntry对象,仅当您需要修改活动目录 (AD) 对象时才需要该对象。如果您的查询返回单个对象是可以的,但是当列出 AD 中的所有对象时,这会大大降低性能。

If you only need to query AD, its better to just use the Propertiescollection of the result object. This will improve performance of the code several times.

如果只需要查询AD,最好只使用Properties结果对象的集合。这将多次提高代码的性能。

This is explained in documentation for SearchResultclass:

这在class 的文档中进行了SearchResult解释:

Instances of the SearchResultclass are very similar to instances of DirectoryEntryclass. The crucial difference is that the DirectoryEntryclass retrieves its information from the Active Directory Domain Services hierarchy each time a new object is accessed, whereas the data for SearchResultis already available in the SearchResultCollection, where it gets returned from a query that is performed with the DirectorySearcherclass.

该实例SearchResult类非常相似的实例 DirectoryEntry类。关键的区别在于,DirectoryEntry每次访问新对象时, 该类都会从 Active Directory 域服务层次结构中检索其信息,而 的数据SearchResult已经存在于 中SearchResultCollection,它是从使用DirectorySearcher该类执行的查询中返回的。

Here is an exampleon how to use the Propertiescollection:

以下是有关如何使用集合的示例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;
}

Documentation for SearchResult.Properties

文档 SearchResult.Properties

Note that properties can have multiple values, that is why we use Properties["name"].Countto check the number of values.

请注意,属性可以有多个值,这就是我们Properties["name"].Count用来检查值数量的原因。

To improve things even further, use the PropertiesToLoadcollection to let the searcher know what properties you are going to use in advance. This allows the searcher to only read the data that is actually going to be used.

要进一步改进,请使用PropertiesToLoad集合让搜索者提前知道您将使用哪些属性。这允许搜索者仅读取实际将要使用的数据。

Note that the DirectoryEntryand DirectorySearcherobjects should be properly disposed in order to release all resources used. Its best done with a usingclause.

请注意,应该正确处理DirectoryEntryDirectorySearcher对象以释放所有使用的资源。最好用一个using条款来完成。