views:

2123

answers:

3

Looking for an example of connecting via ADODB to Active Directory using C#.

My goal is to be able to run a lookup to verify that a user is valid in Active Directory based on one that of that users attributes (user id, email address, etc).

[Would like to stress that using ADODB is a requirement for this, using DirectoryServices is not a valid response.]

My current approach isn't working (exception at cmd.Execute bit):

object parms = null;
object recs = null;
ADODB.Connection conn = new ADODB.Connection();
ADODB.Command cmd = new ADODB.Command();
ADODB.Recordset rs = new ADODB.Recordset();

conn.Open("Provider=ADsDSOObject",obfsUser,obfsPass,0);

cmd.ActiveConnection = conn;
cmd.CommandText = "<LDAP://OU=obfsOU,DC=obfsDC,DC=corp,DC=Net>;;name;subtree";
rs = cmd.Execute(out recs, ref parms, 0);

I'm not sure if/where I'm supposed to provide the server reference and I'm not really sure what the parameteres passed into the cmd.Execute method by ref should be. Not a ton of documentation out there for connecting to ActiveDirectory from C# via ADODB.

conn.State is returning 1 so I believe I am getting an active connection. I think the problem is in the parameters passed to the cmd.Execute() method.

A: 

This works.

Hope this helps someone else having the same need and problems I had.

[Note the lack of an ADODB.Command object and the use of SQL format for the query instead of ADSI format.]

object recs;

ADODB.Connection conn = new ADODB.Connection();
ADODB.Recordset rs = new ADODB.Recordset();

// You may need to provide user id and password instead of empty strings     
conn.Open("Provider=ADsDSOObject", "", "", 0);

// replace <> elements with your server name and OU/DC tree org
string server = "<enter your server name here>";
string start = "OU=<blah>,DC=<blah>,DC=<blah>,DC=<blah>";
string where = "objectClass = '*'";
string qry = string.Format("SELECT cn FROM 'LDAP://{0}/{1}' WHERE {2}", server, start, where);

rs = conn.Execute(qry, out recs, 0);

for (; !rs.EOF; rs.MoveNext())
{
    Console.WriteLine(rs.Fields["cn"].Value.ToString());
}
ScottCher
A: 

Check out Richard Mueller's web site on Active Directory - he specifically has a page on ADO Search Tips for AD:

http://www.rlmueller.net/ADOSearchTips.htm

There's also a slew of excellent reference material on his web site, like Excel sheets with all the AD properties and their characteristics.

Highly recommended!

Marc

marc_s
Thanks for the info and it is good information. However, it doesn't include C# examples and its the parameters required for the C# methods I was having issues with.
ScottCher
+1  A: 

The answer by ScottCher works but it has limitations, notably that you cannot deal with the 1000 record result limit. To do that, the only way is to use a Command object, and believe me, that is a minefield because there is (a) no good documentation on the C# interfaces, and (b) there is incredibly no full solution that can be Googled as of this writing.

I have spent the last bunch of days on this, and have something working that I would like to give back to all the sources I have read with various bits and pieces to the puzzle.

First, as noted in a ton of places (sadly with VB examples only!), if you don't do something special then all ADSI queries are limited to 1000 rows of results. The key to avoiding this is to set the "Page Size" property on the Command object. We'll get to that in a sec, but first we need to get the basic query working using a Command. If you use the original code in this thread, you will get an exception on cmd.Execute complaining about parameters mismatching. You would think that passing in null as the ref object would suffice, especially since the LDAP syntax does not (apparently) have parameters.

I found the answer to this in two places. First, even though you are not explicitly specifying parameters, it would seem that the ":" in the LDAP SQL syntax is enough to make ADO think that parameters are required. Odd, but seemingly true. Second, the CORRECT way to specify the "no parameters" case is to set the value to Type.Missing, not null, as in:

object parms = Type.Missing;

This was key to getting Execute to not throw an exception.

Now with a working Command we can now address the 1000 row limit. This is "simply" by specifying the "Page Size" property on the Command but, as it obvious from the C# interface, it is not the same as a C# property. You need to put it into the Properties collection, but this does not expose a nice collection interface to do that with. After some trial and error, the correct syntax is:

cmd.Properties["Page Size"].Value = 500;

I don't think it is important exactly what the page size is (still playing with that) but setting it to something is enough to tell ADSI to get all the results. And I sincerely hope this helps somebody.

tomo