如何从 Active Directory 获取组织单位列表?

发布于 2024-10-23 20:07:16 字数 185 浏览 1 评论 0原文

我研究过 DirectoryServices 类,它似乎是我需要什么,但我似乎找不到获取组织单位集合所需的类/方法。

大家能给一些建议吗?

I've looked into the DirectoryServices class and it seems to be what I need, but I can't seem to find the classes/methods needed to fetch a collection of Organizational Units.

Can you guys give some suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

我三岁 2024-10-30 20:07:16

您需要使用 System.DirectoryServices 中的适当 DirectorySearcher,并且需要搜索 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);
}

You need to use an appropriate DirectorySearcher from System.DirectoryServices, and you need to search for the organizationalUnit AD class (I would recommend searching based on the objectCategory which is single-valued and indexed - much faster than using objectClass) - something like this:

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);
}
時窥 2024-10-30 20:07:16

我知道这个线程有点旧,但我最近创建了一种比 DirectorySearcher 提供的更有效的通过 DirectoryEntries 进行操作的方法,并且希望分享,因为这是 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();

I know this thread is a little old, but I recently created a more efficient way of maneuvering through DirectoryEntries than the DirectorySearcher provides and wanted to share since this was the top result on Google. This example replicates the OU structure based on an initially specified starting point.

The DN path passed to the first constructor should be in the format "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);
                    }
                }
            });
        });
    }
}

To build, all you need to do is the following:

ADTree Root = null;

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

BuildOUStructure.Wait();
傲性难收 2024-10-30 20:07:16
List<PlayerBO> source = new List<PlayerBO>();

DirectoryEntry root = new DirectoryEntry("LDAP://app.shgbit.com");
DirectoryEntry gbvision = root.Children.Find("OU=UMP");

DirectorySearcher searcher = new DirectorySearcher(gbvision);
searcher.Filter = "(objectClass=computer)";

int index = 1;

foreach (SearchResult each in searcher.FindAll()) 
{
    var box = each.GetDirectoryEntry();
    source.Add(new PlayerBO { Id = index++, Name = box.Properties["name"].Value.ToString(), Description = box.Properties["description"].Value.ToString() });
}

ListViewAD.ItemsSource = new SelectableSource<PlayerBO>(source);
List<PlayerBO> source = new List<PlayerBO>();

DirectoryEntry root = new DirectoryEntry("LDAP://app.shgbit.com");
DirectoryEntry gbvision = root.Children.Find("OU=UMP");

DirectorySearcher searcher = new DirectorySearcher(gbvision);
searcher.Filter = "(objectClass=computer)";

int index = 1;

foreach (SearchResult each in searcher.FindAll()) 
{
    var box = each.GetDirectoryEntry();
    source.Add(new PlayerBO { Id = index++, Name = box.Properties["name"].Value.ToString(), Description = box.Properties["description"].Value.ToString() });
}

ListViewAD.ItemsSource = new SelectableSource<PlayerBO>(source);
复古式 2024-10-30 20:07:16

Jamie 提供的代码运行良好。要回答 MacGuyver 的问题,为了使用 Cast 扩展,您需要在代码中包含对 System.Linq 的引用。我使用此代码来填充在我的 AD 环境中显示 OU 的 TreeView:

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

这是一个带有 TreeView (treeview1) 和 Button (button1) 的简单 Windows 窗体应用程序 - 希望它有帮助!

The code provided by Jamie works nicely. To answer MacGuyver's question, in order to use the Cast extension, you need to include a reference to System.Linq in your code. I'm using this code to populate a TreeView showing the OUs in my AD environment:

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

This is on a simple Windows Forms app with a TreeView (treeview1) and a Button (button1) - hope it helps!

好倦 2024-10-30 20:07:16

您是否看过 DirectorySearcher 方法?

以下是 MSDNbytes.com

Have you looked at the DirectorySearcher method?

Here are some examples at MSDN and bytes.com.

情愿 2024-10-30 20:07:16

这是我的解决方案并且它正在工作:

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

This is my solution and it's working:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文