Как я могу получить список организационных единиц из Active Directory?

Я просмотрел класс DirectoryServices и, похоже, что мне нужно, но я не могу найти классы/методы, необходимые для получения набора организационных единиц.

Можете ли вы, ребята, дать несколько предложений?


person Community    schedule 18.03.2011    source источник


Ответы (6)


Вам нужно использовать соответствующий DirectorySearcher из System.DirectoryServices, и вам нужно искать organizationalUnit класс AD (я бы рекомендовал искать на основе objectCategory, который является однозначным и индексированным - намного быстрее, чем использование objectClass) - что-то вроде этого:

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

DirectoryEntry startingPoint = new DirectoryEntry("LDAP://DC=YourCompany,DC=com");

DirectorySearcher searcher = new DirectorySearcher(startingPoint);
searcher.Filter = "(objectCategory=organizationalUnit)";

foreach (SearchResult res in searcher.FindAll()) 
{
    orgUnits.Add(res.Path);
}
person marc_s    schedule 18.03.2011

Я знаю, что эта ветка немного устарела, но недавно я создал более эффективный способ маневрирования через DirectoryEntries, чем предлагает DirectorySearcher, и хотел поделиться, поскольку это был лучший результат в Google. В этом примере реплицируется структура OU на основе изначально заданной начальной точки.

Путь DN, передаваемый первому конструктору, должен иметь формат «LDAP://OU=StartingOU,DC=test,DC=com».

using System.DirectoryServices;
using System.Threading.Tasks;

public class ADTree
{
    DirectoryEntry rootOU = null;
    string rootDN = string.Empty;
    List<ADTree> childOUs = new List<ADTree>();

    public DirectoryEntry RootOU
    {
        get { return rootOU; }
        set { rootOU = value; }
    }

    public string RootDN
    {
        get { return rootDN; }
        set { rootDN = value; }
    }

    public List<ADTree> ChildOUs
    {
        get { return childOUs; }
        set { childOUs = value; }
    }

    public ADTree(string dn)
    {
        RootOU = new DirectoryEntry(dn);
        RootDN = dn;
        BuildADTree().Wait();
    }

    public ADTree(DirectoryEntry root)
    {
        RootOU = root;
        RootDN = root.Path;
        BuildADTree().Wait();
    }

    private Task BuildADTree()
    {
        return Task.Factory.StartNew(() =>
        {
            object locker = new object();
            Parallel.ForEach(RootOU.Children.Cast<DirectoryEntry>().AsEnumerable(), child =>
            {
                if (child.SchemaClassname.Equals("organizationalUnit"))
                {
                    ADTree ChildTree = new ADTree(child);
                    lock (locker)
                    {
                        ChildOUs.Add(ChildTree);
                    }
                }
            });
        });
    }
}

Для сборки вам нужно сделать следующее:

ADTree Root = null;

Task BuildOUStructure = Task.Factory.StartNew(() =>
{
    ADTree = new ADTree("LDAP://ou=test,dc=lab,dc=net");
});

BuildOUStructure.Wait();
person Jaime Still    schedule 14.01.2015
comment
Ошибка 1 «System.DirectoryServices.DirectoryEntries» не содержит определения для «Cast», и не может быть найден метод расширения «Cast», принимающий первый аргумент типа «System.DirectoryServices.DirectoryEntries» (вы пропустили директиву using или ссылка на сборку?) - person MacGyver; 27.09.2019
comment
есть идеи, почему эта линия не работает? Parallel.ForEach(RootOU.Children.Cast‹DirectoryEntry›().AsEnumerable(), child =› - person MacGyver; 27.09.2019

Код, предоставленный Джейми, прекрасно работает. Чтобы ответить на вопрос MacGuyver, чтобы использовать расширение Cast, вам нужно включить ссылку на System.Linq в свой код. Я использую этот код для заполнения TreeView, показывающего OU в моей среде AD:

using System;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.DirectoryServices;
using System.Collections.Generic;
using System.DirectoryServices.ActiveDirectory;

namespace WindowsFormsApp8
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            treeView1.Nodes.Clear();
            string top = string.Format("LDAP://DC={0}", Domain.GetCurrentDomain().Name.Replace(".", ",DC="));
            ADTree tree = null;

            Task BuildOUStructure = Task.Factory.StartNew(() =>
            {
                tree = new ADTree(top);
            });

            BuildOUStructure.Wait();
            foreach(ADTree t in tree.ChildOUs)
            {
                TreeNode node = new TreeNode(t.RootOU.Path);
                treeView1.Nodes.Add(node);
                if(t.ChildOUs.Count > 0)
                {
                    AddChildren(node, t);
                }
            }
        }

        private void AddChildren(TreeNode parent, ADTree tree)
        {
            foreach(ADTree t in tree.ChildOUs)
            {
                TreeNode node = new TreeNode(t.RootOU.Path);
                parent.Nodes.Add(node);
                if(t.ChildOUs.Count > 0)
                {
                    AddChildren(node, t);
                }
            }
        }
    }

    public class ADTree
    {
        DirectoryEntry rootOU = null;
        string rootDN = string.Empty;
        List<ADTree> childOUs = new List<ADTree>();

        public DirectoryEntry RootOU
        {
            get { return rootOU; }
            set { rootOU = value; }
        }

        public string RootDN
        {
            get { return rootDN; }
            set { rootDN = value; }
        }

        public List<ADTree> ChildOUs
        {
            get { return childOUs; }
            set { childOUs = value; }
        }

        public ADTree(string dn)
        {
            RootOU = new DirectoryEntry(dn);
            RootDN = dn;
            BuildADTree().Wait();
        }

        public ADTree(DirectoryEntry root)
        {
            RootOU = root;
            RootDN = root.Path;
            BuildADTree().Wait();
        }

        private Task BuildADTree()
        {
            return Task.Factory.StartNew(() =>
            {
                object locker = new object();
                Parallel.ForEach(RootOU.Children.Cast<DirectoryEntry>().AsEnumerable(), child =>
                {
                    if (child.SchemaClassName.Equals("organizationalUnit"))
                    {
                        ADTree ChildTree = new ADTree(child);
                        lock (locker)
                        {
                            ChildOUs.Add(ChildTree);
                        }
                    }
                });
            });
        }
    }
}

Это простое приложение Windows Forms с TreeView (treeview1) и кнопкой (button1) — надеюсь, это поможет!

person LordPupazz    schedule 27.09.2019
comment
Спасибо за ответ на вопрос @MacGyver! Я был безумно занят в последнее время - person Jaime Still; 04.10.2019

Вы видели метод DirectorySearcher?

Вот несколько примеров в MSDN и bytes.com .

person Louis Waweru    schedule 18.03.2011

Это мое решение, и оно работает:

List<string> DisplayedOU = new List<string>();
int step = 0;
string span = "<span style='margin-left:6px;'> -- </span>";

private void getOU2()
{
    string strRet = "";
    DirectoryEntry domainRoot = new DirectoryEntry("LDAP://uch.ac/OU=ALL,DC=uch,DC=ac", "user", "pass");

    // set up directory searcher based on default naming context entry
    DirectorySearcher ouSearcher = new DirectorySearcher(domainRoot);

    // SearchScope: OneLevel = only immediate subordinates (top-level OUs); 
    // subtree = all OU's in the whole domain (can take **LONG** time!)
    ouSearcher.SearchScope = SearchScope.Subtree;
    // ouSearcher.SearchScope = SearchScope.Subtree;

    // define properties to load - here I just get the "OU" attribute, the name of the OU
    ouSearcher.PropertiesToLoad.Add("ou");

    // define filter - only select organizational units
    ouSearcher.Filter = "(objectCategory=organizationalUnit)";

    int cnt = 0;


    foreach (SearchResult deResult in ouSearcher.FindAll())
    {
        string temp = deResult.Properties["ou"][0].ToString();

        strRet += FindSubOU(deResult.Properties["adspath"][0].ToString(), cnt);

    }

    Literal1.Text = strRet;
}


private string FindSubOU(string OU_Path, int cnt)
{
    string strRet = "";

    DirectoryEntry domainRoot = new DirectoryEntry(OU_Path, "user", "pass");

    // set up directory searcher based on default naming context entry
    DirectorySearcher ouSearcher = new DirectorySearcher(domainRoot);

    // SearchScope: OneLevel = only immediate subordinates (top-level OUs); 
    // subtree = all OU's in the whole domain (can take **LONG** time!)
    ouSearcher.SearchScope = SearchScope.Subtree;
    // ouSearcher.SearchScope = SearchScope.Subtree;

    // define properties to load - here I just get the "OU" attribute, the name of the OU
    ouSearcher.PropertiesToLoad.Add("ou");

    // define filter - only select organizational units
    ouSearcher.Filter = "(objectCategory=organizationalUnit)";

    //adspath
    // do search and iterate over results
    foreach (SearchResult deResult in ouSearcher.FindAll())
    {
        string temp = deResult.Properties["ou"][0].ToString();

        if (!DisplayedOU.Contains(deResult.Properties["ou"][0].ToString()))
        {
            string strPerfix = "";

            for (int i = 0; i < step; i++)
                strPerfix += span;

            strRet += strPerfix + ++cnt + ". " + deResult.Properties["ou"][0].ToString() + " ----> " + deResult.Properties["adspath"][0].ToString() + "<br />";

            DisplayedOU.Add(deResult.Properties["ou"][0].ToString());

            step++;

            strRet += FindSubOU(deResult.Properties["adspath"][0].ToString(), cnt);

            step--;
        }

    }


    return strRet;
}
person ghazizadeh    schedule 05.08.2017

person    schedule
comment
Если вы публикуете образцы кода, XML или данных, пожалуйста, выделите эти строки в текстовом редакторе и нажмите кнопку образцов кода ( { } ) на панели инструментов редактора, чтобы красиво отформатировать и выделить синтаксис! - person marc_s; 18.03.2011