.NET - Getting list of PC Names from via LDAP into a DataSet

tgabe213

2[H]4U
Joined
Aug 27, 2007
Messages
3,684
I'm trying to query LDAP for a list of PC names, and input them into a DataTable. I can get the query to run, and input them directly into a ListBox, but I'm not able to sort that way, which is why I'm trying to use a DataTable.

Code:
        public void ldapQuery()
        {
            string server = ""; //Insert Domain controller server here
            string adminUser = ""; //Insert an admin user account here
            string adminPass = ""; //Password for above username

            DirectoryEntry de = new DirectoryEntry();
            de.Path = "LDAP://" + server + "";
            de.Username = adminUser;
            de.Password = adminPass;

            try
            {
                DirectorySearcher ser = new DirectorySearcher();
                ser.Filter = "(&ObjectCategory=computer)"; //Only allows Computers to be returned in results.
                SearchResultCollection results = ser.FindAll();

                DataTable dt = new DataTable();
                DataRow pcRow;
                pcRow = dt.NewRow();

                foreach (SearchResult res in results)
                {
                    string[] temp = res.Path.Split(','); //temp[0] would contain the computer name ex: cn=computerName
                    pcRow["pcName"] = temp[0].Substring(10);//returns everything after LDAP://CN= until end of temp[0].
                }

                dt.Rows.Add(pcRow);
                lbItems.DataSource = dt;
                lbItems.DisplayMember = "pcName";
                lbItems.ValueMember = "pcName";
               
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                de.Dispose();//Clean up resources
            }
        }

I think the issue with the code above is the DataTable, adding rows to the DataTable, and then binding it to the DataTable.

If I replace
Code:
pcRow["pcName"] = temp[0].Substring(10);//returns everything after LDAP://CN= until end of temp[0].

with

Code:
lbItems.Items.Add(temp[0].Substring(10));

then the PC names are added to the list box. The problem is that they are not sorted. I'm not able to add items to an array prior to the listbox in the foreach loop either.

Any ideas? I'm thinking I need to create a new row for every item returned by the search. Also, if anyone knows a way to sort my search results, I could do that and bypass the datatable.
 
DirectorySearcher has a Sort property according to google? (though maybe it doesn't take a comparison functor)
 
DirectorySearcher has a Sort property according to google? (though maybe it doesn't take a comparison functor)

That's what I'm finding, but when I try to add this, it no longer returns any results.
Code:
                ser.Filter = "(&ObjectCategory=computer)"; //Only allows Computers to be returned in results.
                SortOption option = new SortOption("computer", System.DirectoryServices.SortDirection.Ascending);
                ser.Sort = option;

This breaks my search. I think that the sort option "computer" is where I'm not actually sure what to put in there.
 
If neither DirectorySearcher nor SearchResultCollection (unordered?) can be persuaded to give in to a sort order, and if DataTable is a view (I'd assume it's a M/C?!) without sorting, then I'd just give in and put the data is a list or something and sort that before adding it to the DataTable. You claim "I'm not able to add items to an array prior to the listbox in the foreach loop either." but don't explain what the problem is (inelegant, perhaps, but should be perfectly functional).

(If it isn't already obvious, I haven't written a line of C#/.NET in my life)
 
If neither DirectorySearcher nor SearchResultCollection (unordered?) can be persuaded to give in to a sort order, and if DataTable is a view (I'd assume it's a M/C?!) without sorting, then I'd just give in and put the data is a list or something and sort that before adding it to the DataTable. You claim "I'm not able to add items to an array prior to the listbox in the foreach loop either." but don't explain what the problem is (inelegant, perhaps, but should be perfectly functional).

(If it isn't already obvious, I haven't written a line of C#/.NET in my life)

Code:
                string[] pcArray;
                int x = 0;
                foreach (SearchResult res in results)
                {
                    string[] temp = res.Path.Split(','); //temp[0] would contain the computer name ex: cn=computerName
                    //returns everything after LDAP://CN= until end of temp[0].
                    pcArray[x] = temp[0].Substring(10);
                    x++;
                }

This does not work. The error is with pcArray inside the foreach loop. It says "Use of unassigned local variable 'pcArray'. The x++; has no issues though. I've seen elsewhere after a bit of googling that adding items to an array like this inside a foreach loop isn't possible.
 
A data table seems like on overly heavy data structure to use just to accomplish a sort.
You might try an ArrayList(just replace your data table code with arraylist code), which has a sort method, or barring that you can output the contents of an arraylist to an array and sort that.
 
See my last post. Is ArrayList going to solve the problem that I'm running in to with Array above?
 
See my last post. Is ArrayList going to solve the problem that I'm running in to with Array above?

Try it :)

However, you can add entries to an arraylist with the .add (I think, been awhile) method.

just foreach your results collection, and add the result snippet you want to the arraylist.



eg something like this:

Code:
ArrayList list = new ArrayList();
foreach (SearchResult res in results)
                {
                    string[] temp = res.Path.Split(',');                  
                    list.Add(temp[0].Substring(10));
                }
string[] list2 = (string[])ArrayList.ToArray(typeof string);

That's from memory, you'll have to check the syntax.
 
That works, kinda. I'm having trouble returning the array now, and I wonder if I missed something. Intellisense red underlines 'ldapQuery' in the method name and the error says that "not all code paths return a value". Is it because I'm returning pcArray from inside the try block? If I create a test array outside of the try/catch/finally block and 'return it', the error goes away.

Code:
        private void btnConnect_Click(object sender, EventArgs e)
        {
            string[] pcArray = ldapQuery(txtLdap1.Text, txtUsername.Text, txtPassword.Text);
        }

        //********Connection Methods********//

        private string[] ldapQuery(string server, string adminUser, string adminPass)
        {
            DirectoryEntry de = new DirectoryEntry();
            de.Path = "LDAP://" + server + "";
            de.Username = adminUser;
            de.Password = adminPass;

            try
            {
                DirectorySearcher dirSearcher = new DirectorySearcher(de);
                dirSearcher.Filter = "(&ObjectCategory=computer)";
                SearchResultCollection results = dirSearcher.FindAll();

                ArrayList list = new ArrayList();
                foreach (SearchResult res in results)
                {
                    string[] temp = res.Path.Split(',');
                    list.Add(temp[0].Substring(10));
                }
                string[] pcArray = (String[])list.ToArray(typeof(string));
                Array.Sort(pcArray);
[B]                return pcArray;[/B]
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error: " + ex);
            }
            finally
            {
                de.Dispose();
            }
        }
 
You probably shouldn't return from within the try block... I'd move it to after the finally block. But that means you'll have to adjust your scope on pcArray as well.
 
You probably shouldn't return from within the try block... I'd move it to after the finally block. But that means you'll have to adjust your scope on pcArray as well.

That's what I figured. How can I adjust the scope of the pcArray? By declaring it outside of the try block? Then it won't have access to the Array list. If I declare the arraylist outside of the try block, then I can't use it inside the try block.
 
Try declaring it outside of the try block and initialize to null

Code:
string[] pcArray = null;
try
{
<snip>
pcArray = (String[])list.ToArray(typeof(string));
<snip>
}
catch{}
finally{}
return pcArray;
 
ArrayList would work, I like using List<string> myself. This should do it I think(don't have VS to compile it on this machine)

Code:
private void btnConnect_Click(object sender, EventArgs e)
{
	List<string> pcArray = ldapQuery(txtLdap1.Text, txtUsername.Text, txtPassword.Text);
}

private List<string> ldapQuery(string server, string adminUser, string adminPass)
{
	DirectoryEntry de = new DirectoryEntry();
	de.Path = "LDAP://" + server + "";
	de.Username = adminUser;
	de.Password = adminPass;
	List<string> tList = new List<string>();
	try
	{
		DirectorySearcher dirSearcher = new DirectorySearcher(de);
		dirSearcher.Filter = "(&ObjectCategory=computer)";
		SearchResultCollection results = dirSearcher.FindAll();

		foreach (SearchResult res in results)
		{
			string[] temp = res.Path.Split(',');
			tList.Add(temp[0].Substring(10));
		}
		
		tList.Sort();
	}
	catch (Exception ex)
	{
		MessageBox.Show("Error: " + ex);
	}
	finally
	{
		de.Dispose();
                return tList;
	}
}
 
That worked! But why?

Before, I had tried declaring the array outside of the try block, but on the inside, it didn't have access to the already declared array. Is it because you suggested initializing it to null?
Try declaring it outside of the try block and initialize to null

Code:
string[] pcArray = null;
try
{
<snip>
pcArray = (String[])list.ToArray(typeof(string));
<snip>
}
catch{}
finally{}
return pcArray;
 
That worked! But why?

Before, I had tried declaring the array outside of the try block, but on the inside, it didn't have access to the already declared array. Is it because you suggested initializing it to null?

If your code fails somewhere in your try, you will never get a value returned as your logic will skip over to your catch. A value HAS to be returned

You can either return a value in both the try and a catch or like you did here, return a value at the end after the try/catch blocks. Sometimes you may want to return a special value in the catch section so the caller of the function knows that it errored out.
 
I understand that, but before taking Pwl's suggestion, even though I had a return in the try, or outside of the block, the method name still said that nothing was being returned.
 
In post 10, you have a return in the try, but nothing in the catch. It would be possible to error out and hit the catch portion and never have anything returned.

Post the code you're talking about that didn't work with the return outside of the try/catch.
 
It's because if you don't explicitly assign it a value, the compiler sees the catch block as a section of code that doesn't assign a value, and all of the try block might not run. You can assign it null because it's an instance of a class. You'll get a similar error if you try to read from a variable that doesn't have a definite assignment:
Code:
			string x;
		
			try
			{
				x="yes";
			}
			catch
			{
				
			}
			
			string y = x;
 
Pwyl's hitting on a good habit: initialize objects outside of the "try" to at least something (null/Nothing, int.Zero, string.Empty, etc.). You can instantiate complex objects within the "try" block, but it's good practice to at least provide a starting value in such occasions when comparing values after a try-catch-finally block.
 
Back
Top