How can I get a list of Organizational Units from Active Directory?
Asked Answered
S

6

12

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?

Sunlight answered 18/3, 2011 at 1:26 Comment(0)
P
21

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);
}
Prophesy answered 18/3, 2011 at 6:5 Comment(0)
H
5

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();
Hotbox answered 14/1, 2015 at 21:47 Comment(2)
Error 1 'System.DirectoryServices.DirectoryEntries' does not contain a definition for 'Cast' and no extension method 'Cast' accepting a first argument of type 'System.DirectoryServices.DirectoryEntries' could be found (are you missing a using directive or an assembly reference?)Lindeberg
any idea why this line doesn't work? Parallel.ForEach(RootOU.Children.Cast<DirectoryEntry>().AsEnumerable(), child =>Lindeberg
B
4
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);
Boccioni answered 18/3, 2011 at 2:55 Comment(1)
If you post code, XML or data samples, please highlight those lines in the text editor and click on the "code samples" button ( { } ) on the editor toolbar to nicely format and syntax highlight it!Prophesy
B
3

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!

Burmeister answered 27/9, 2019 at 18:9 Comment(1)
Thanks for answering @MacGyver's question! I've been crazy busy latelyHotbox
S
0

Have you looked at the DirectorySearcher method?

Here are some examples at MSDN and bytes.com.

Sherikasherill answered 18/3, 2011 at 1:45 Comment(0)
R
0

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;
}
Redhot answered 5/8, 2017 at 3:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.