If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

Populate TreeView with Active Directory objects

Active Directory TreeView / Select AD Container Dialog

This is a WinForms dialog window (I have a WPF version as well, if anyone wants that just let me know) that will show all containers and OUs in a specified domain and let the user select a container/OU. You can then retrieve the full distinguished name for the OU they selected by checking the SelectedContainerPath property after you have shown the dialog window.

UPDATED 10/11/2011

I've removed the old version of this control and replaced it with a new version which is actually a proper dialog window rather than a control and is a lot faster, better written, no longer requires you to provide the OU/container icons yourself, and is used more similarly to other standard .NET dialog windows

Here's a screenshot of the new version in action

There's an example project that shows how to use the dialog window within the attached solution, but here's a basic example anyway:

If you don't want it to show the domain tree for the current user's domain, you can set the DomainName property to specify an alternate domain and the Username and Password properties to specify alternate credentials if required. Here's a better example showing this:

Re: Populate TreeView with Active Directory objects

I dont understand the first question, the custom TreeNode class I wrote/displayed in the above posts provides a property named DistinguishedName so you just access that property on the selected node... can you provide an example of what exactly you are trying to do and maybe I can show you how to go about it?

As for the second question, you could do that but it would require you to re-work the code I've provided because my code just adds all of the nodes to a single parent node that is stored in memory and then when that has all finished it just adds that parent node to the treeview, so you would have to change it so that instead of adding it to a node in memory it adds it to the actual treeview on screen and because that recursive function is running in a background thread that would mean you need to create another delegate etc to handle the cross thread call. Basically, I'm sure it could be done but personally I dont think its worth the hassle as it doesnt take very long (on the domains I tested it on anyway) to build the tree and its not as if the UI freezes while its being built or anything so there's little advantage to doing it.

Re: Populate TreeView with Active Directory objects

Originally Posted by chris128

I dont understand the first question, the custom TreeNode class I wrote/displayed in the above posts provides a property named DistinguishedName so you just access that property on the selected node... can you provide an example of what exactly you are trying to do and maybe I can show you how to go about it?

Thank you for the quick reply. I have add a button, that will want to set a public variable from a parent form with the DistinguishedName. Then Close the current form and return to the parent.

Currently to get past the issue, I went ahead and the DistinguishedName to the tag property.

Re: Populate TreeView with Active Directory objects

Duh.... Now I see it. Great, that works perfectly!!!!!!

I do have a little more complicated question.

How does the progbar work? I don't see where you are increasing it. Also the progbar will work fine for the first time the form is load from a parent form. After I close the from and return to the parent form, and rerun that form again, the progbar does not work. Its there on the screen, but nothing happens with it.

I have tried stepping through the code, I just don't see were you increase or move the progress bar.

Re: Populate TreeView with Active Directory objects

No worries,

The progress bar I was using was set to marquee style, which means it just constantly moves in a constant loop animation, so there is no increasing etc. If you wanted to get clever you could somehow make an estimate of how many objects in AD there are to load before you make the progress bar appear and then you could just increase the progress bar value by 1&#37; each time 1% of the objects has been loaded etc but again I think its too much work to be worth it personally.

Re: Populate TreeView with Active Directory objects

I like the marquee affect. It just nice to see that something is happening in the background.

However, when I reload the form with the progbar, The marque affect does not start again.

Load program (main form)
Click a button the load the childform with the progbar and adtreeview objects.
--- Everying workgreat. ProgBar runs, ADTreeView is built with ADTreeNodes
Drill Down through the ADTreeNodes, select the ADTreeNode I want.
Click a button that returns the selected ADTreeNode DistinguishedName and Close the child form.
Return to the main form.

Again, Click the same button to load the chilform with the progbar and adtreeview objects.
---- This were the ProgBar marquee does not run / work. The building of the ADTreeView does and show does the statuslbl indication which node its working on.

So here the progress bar style is being set back to Blocks, which is the only way to stop the marquee really (as far as I know anyway) other than just making the progress bar invisible. So you just need to set it back to Marquee style using the following code before you call the LoadDirectoryObjectsAsync method in your button click event:

Re: Populate TreeView with Active Directory objects

Wonderful!!!

That solved that problem.

Thanks for all your help and advice. Your sample project was the information I needed, not only for build an AD tree, but using threads too.

What i have now discovered is that if I use the X to close the form while the treeview is building and then reopen the form before the thread completes, I get identical trees, two roots. Opps... I need to add a form unload event and abort the tread.

My main for is to copy a file to multiple computers. I have created a button to load a listbox from a textfile. I have another button that load the adtreeview form. After the builds and I select the adtreenode and use the select button. It return the distinguishedname. I use that for the root path for another connection to AD to get all the computer type objects in that path.

Of course I have a text box of what file I want to copy and a text box of where I want to copy that file too.

The very cool thing that I have been working on is using multithreading for the copy process. Original I tried to create and manage my own threads. I was using a TrackbarSlider object to set how many threads I want to create, with a max of 10. I for the life of me could not correctly figure out how to manage the treads when there where more computers than threads. I finally discovered the threadpool class. YEAH!!! I set the desired max threads for the threadpool. I have an array of all my computer names, I just use a for each statement for the list of computers, and use the threadpool.queuuserworkitem to feed the threadpool my copy funcation and computer name. Works great, I don't have to manage the treadstates.

Threading.ThreadPool.SetMaxThreads(TrBr_NumThread.Value, TrBr_NumThread.Value)
For Each item In CC
Threading.ThreadPool.QueueUserWorkItem(New Threading.WaitCallback(AddressOf Copy), item)
Next

This one section manges all my threads. (CC is my array of computer names, Copy is my function to copy the set file to each computer in the CC array)

I have learned lots with this simple little copy utility. There are something I need to fix and improve, but the core is working fine. I use a multi-line textbox to display status messages. Now with multi-treading, the status messages get out of order. Its a simple fix, but something shows the threads are running and I have multiple copy sessions running.

The last thing I need to fix is my logfile that get created and logs if each copy process is successfull or not. Currently nothing is getting written to the file, but I think it has todo with not using the delegates todo the writeline method.

Re: Populate TreeView with Active Directory objects

That sounds good I'm glad you got it working. The ThreadPool class is something I need to play around with as I've never really tried using it much to be honest because I've always just been doing things that require one or two background threads, never loads like you are talking about.

As for writing to a log file, you shouldnt need to use a delegate to write to a file I dont think as its not a cross thread call (assuming your just trying to write information gathered from the same thread to the file anyway).

Re: Populate TreeView with Active Directory objects

Hello,
I am very interesting by your application.
I am network administrator and I begin with VB 2008 Express.
The fact is I would like to reset some local administrator passwords on computers which are in my domain.

To do that, I take your form that I modified according to my area and I just want to know :

1° How can I get the Distinguished Name of the selected node in a textbox?

e.g: if I click on the node (myComputer) which is in the parent node (Computers) which is in the domain (my.domain.com) I would like to return "LDAP://CN=myComputer,OU=Computers,DC=my,DC=domain,DC=com" in a textbox.

2° Is it possible to get Computers of a selected node in a treeview and post them directly in a listbox ?

Re: Populate TreeView with Active Directory objects

1&#176; How can I get the Distinguished Name of the selected node in a textbox?
The ADTreeView control I have created in this article returns an ADTreeNode when you use the SelectedNode property of the treeview, and because my ADTreeNode class has a property that gets the Distinguished Name, you can simply do this:

Re: Populate TreeView with Active Directory objects

If you right click on the toolbox and go to Choose Items (or it might be Select Items) then you can select the ADTreeView from somewhere within that new window that appears (its been a while since I did anything like this as I have been using WPF for the last few months). Also I think if you have a custom UserControl in your project then when you build the project it adds the control to your toolbox right at the top.

EDIT: Oh and I just checked and the project I uploaded to this thread is already targetting the .NET Framework 2.0 so I dont know why you are having problems. What exactly happens when you try and run it?

Re: Populate TreeView with Active Directory objects

Since I could not open the project using VS 2005, I defined a new VB project in VS 2005 and imported the existing files.

The ADTreeView class comes upwith an error on:

Dim bgthread As New Threading.Thread(AddressOf bgthread_DoWork)

I beleive the error is because bgthread_DoWork expects a parameter. This is the error message:

Error 1 Overload resolution failed because no accessible 'New' can be called with these arguments:
'Public Sub New(start As System.Threading.ParameterizedThreadStart)': Method 'Private Sub bgthread_DoWork(RootDirectoryEntry As System.DirectoryServices.DirectoryEntry)' does not have the same signature as delegate 'Delegate Sub ParameterizedThreadStart(obj As Object)'.
'Public Sub New(start As System.Threading.ThreadStart)': Method 'Private Sub bgthread_DoWork(RootDirectoryEntry As System.DirectoryServices.DirectoryEntry)' does not have the same signature as delegate 'Delegate Sub ThreadStart()'. C:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\ADTreeView\ADTreeView\ADTreeView.vb 54 13 ADTreeView

Also, form2 can not be opened, maybe because the ADTreeView is not valid.

Re: Populate TreeView with Active Directory objects

Hmm ok I'll install VS 2005 on a virtual machine later today (or possibly tomorrow) and try get it working then upload the solution

EDIT: Actually I just realised, I didnt have Option Strict On in the solution I uploaded (tut tut) and when I turn that on I get the same error you mentioned. Its pretty easy to sort out, just need to change the type casting for that DoWork method a little. One second and I'll post the code.

Re: Populate TreeView with Active Directory objects

Hi Chris,

Well done. That solved the thread problem.

I still had to fidget with Form2 - in the end I just removed it and created it from the beginning. For some reason when you add the AdTreeView to the form it is generated as ADTreeView.ADTreeView in the designer script. I just changed it back to ADTreeView and it worked.

The next step for me is to be able to see the Users in the security groups. I wonder why did you implement this ?

Then, I need to be able to select some of the security Groups and Organization Units to generate a Filter string to get all the Users from the selected items.

Re: Populate TreeView with Active Directory objects

Being able to see the users in each group is totally different because groups do not contain child objects in the same way that containers and OUs do. You would have to use something like what I have done in this thread to get all of the users and then add them to the treeview: http://www.vbforums.com/showthread.php?t=535091

Also, this is a codebank thread and as such it is not really for asking questions so if you do still have more questions that are not strictly related to this ADTreeView control (finding out which users are in a group is not really related) then please post them in the VB.NET part of the forum and if necessary then just put a link to this thread in there so that people know what you are working with

Re: Populate TreeView with Active Directory objects

OK I have uploaded a new version of the project to the original post in this thread. The new version will retrieve the members of groups now and display them in the treeview, like so:

One thing I have not done yet is make this recursive. So if you have a group that contains another group that contains more groups and users then you will only see the first group and the group that it contains, not the groups and users within that nested group if you see what I mean.
I have also tidied up other parts of the code and made it so that the SelectedNode property returns an ADTreeNode not just a normal TreeNode now
Like I said, check the first post in this thread for a new attachment named "NewVersion-ADTreeViewInForm"

Re: Populate TreeView with Active Directory objects

It seems this is what im looking for... I have some questions... do you have a new version? one that fixes the nested group? does this error also applies to OU that contains more OU that cotains some more OU... etc...

Re: Populate TreeView with Active Directory objects

No it only applies to groups. There wouldnt be much point in an Active Directory treeview if it didnt display OUs inside OUs

The groups are a special case and not something that I consider to be broken. I dont think you can even do that in the Microsoft Active Directory Users & Computers snap in, expand groups in the treeview to see their members I mean. I just added that 'feature' because someone requested it.

Re: Populate TreeView with Active Directory objects

Its about time I improved this so I'll add a few new features, tidy it up, and post a new version soon - as a proper control library DLL rather than just an example project with the control in. That should make it easier for you to add it to your own program

Re: Populate TreeView with Active Directory objects

OK well this is still not 100% finished and although I have tested it, I havent tested it thoroughly yet, but here's a new version (see file attached to this post) that is built as a Control. Just add a reference to the DLL to your project. If you want to add the control to your toolbox you can just go to "Choose Items" on the toolbox and browse to the DLL.

New features include:1. The LoadCompleted event now has a property that is passed in to it that lets you check to see if the event was raised because the load was cancelled2. A new method named CancelLoad which lets you cancel the treeview load if it is currently in progress. This does not cancel immediately though, just the next time it starts to load a new tree in the object tree.3. A property named ExpandGroups - set to True to make groups expandable to show their members in the treeview. Leave as the default False to just have groups show in the tree as a non-expandable item4. 2 new properties named AuthUsername and AuthPassword that you set instead of passing the username and password in to the LoadDirectoryObjectsAsync method. 5.A LoadOnDemand property - Set to True to make the treeview just load the first 'level' of items in the root path that you specified and then only load child objects when a node is expanded. This means that the initial load is much faster but I have not yet made this work on a background thread so the control will freeze for a second when you expand a node.6. A LoadInProgress property which you can check to see if the tree is currently being loaded in a background thread7. A LoadCancelled property, which you can check to see if the tree is 'cancel pending'.

So if you want to try it out and let me know any problems or comments you have that would be great. Once I have finished tidying a few bits up and testing it more then I will update the first post in this thread and add it to there.

Re: Populate TreeView with Active Directory objects

Re: Populate TreeView with Active Directory objects

I get this error when I run the form with the control:

An error occurred creating the form. See Exception.InnerException for details. The error is: Could not load file or assembly 'AdTreeViewCtrl, Version=1.3.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. An attempt was made to load a program with an incorrect format.

I am a bit of a n00b so do shout of I have done something wrong ... I have not told it where to point to - just want to know if the form runs....