views:

1150

answers:

2

I'm trying to run a simple LDAP query using directory services in .Net.

    DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://someserver.contoso.com/DC=contoso,DC=com");
    directoryEntry.AuthenticationType = AuthenticationTypes.Secure;

    DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry);

    directorySearcher.Filter = string.Format("(&(objectClass=user)(objectCategory=user) (sAMAccountName={0}))", username);

    var result = directorySearcher.FindOne();
    var resultDirectoryEntry = result.GetDirectoryEntry();

    return resultDirectoryEntry.Properties["msRTCSIP-PrimaryUserAddress"].Value.ToString();

And I'm getting the following exception:

System.Runtime.InteropServices.COMException (0x80005000): Unknown error (0x80005000)
  at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
  at System.DirectoryServices.DirectoryEntry.Bind()
  at System.DirectoryServices.DirectoryEntry.get_AdsObject()
  at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
  at System.DirectoryServices.DirectorySearcher.FindOne()

As a snippet in a Console app, this works. But when I run it as part of a WCF service (run under the same credentials), it throws the above exception.

Any suggestions?

Thanks

+2  A: 

It's a permission problem.

When you run the console app, that app runs with your credentials, e.g. as "you".

The WCF service runs where? In IIS? Most likely, it runs under a separate account, which is not permissioned to query Active Directory.

You can either try to get the WCF impersonation thingie working, so that your own credentials get passed on, or you can specify a username/password on creating your DirectoryEntry:

DirectoryEntry directoryEntry = 
    new DirectoryEntry("LDAP://someserver.contoso.com/DC=contoso,DC=com", 
                       userName, password);


OK, so it might not be the credentials after all (that's usually the case in over 80% of the cases I see).

What about changing your code a little bit?

DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry);
directorySearcher.Filter = string.Format("(&(objectClass=user)(objectCategory=user) (sAMAccountName={0}))", username);

directorySearcher.PropertiesToLoad.Add("msRTCSIP-PrimaryUserAddress");

var result = directorySearcher.FindOne();

if(result != null)
{
   if(result.Properties["msRTCSIP-PrimaryUserAddress"] != null)
   {
      var resultValue = result.Properties["msRTCSIP-PrimaryUserAddress"][0];
   }
}

My idea is: why not tell the DirectorySearcher right off the bat what attribute you're interested in? Then you don't need to do another extra step to get the full DirectoryEntry from the search result (should be faster), and since you told the directory searcher to find that property, it's certainly going to be loaded in the search result - so unless it's null (no value set), then you should be able to retrieve it easily.

Marc

marc_s
+1: You're faster
Arthur
I'm logged into the server where this process is running as the service account I have configured the WCF service to run as - so they are using the same credentials surely?
GodEater
OK - can you step through the code (or write out trace messages) to find out where exactly that exception happens??
marc_s
The 0x80005000 is a pretty "boilerplate" error and can mean just about anything......
marc_s
A: 

Check this out:http://msdn.microsoft.com/en-us/library/ms180891(VS.80).aspx

Marius