If all of the domains are part of the same forest, you should be able to do a global catalog seach (GC:// instead of LDAP://). You only get a partial attribute set back but you can get the distinguishedName and then to a standard LDAP:// lookup.
If you're in the situation where you have different domains that are in different forests, then one simple way would be to build a look-up table of your NetBIOS domain names. For each forest, you do a subtree search of CN=Partitions,CN=Configuration,DC=YourDomain,DC=com with a filter of (netBIOSname=*) and you'll get back a list of the domains in that forest. The dnsRoot attribute will give you the DNS name of the domain and you can just use that to bind to, or do a DNS lookup of it and use the first address you get to bind to. Or you can use the dnsRoot to create System.DirectoryServices.ActiveDirectory.DirectoryContext to with a DirectoryContextType of DirectoryServer to get you a reference to the domain controller. Or you could use nCName (gives you the namingContext of the domain).
I can probably help more, if you can provide more details, or if any of that wasn't clear.
Additional:
- You can get a DirectoryEntry by doing a 'serverless bind' by just supplying the distinguishedName of an object in the directory. E.g. "LDAP://CN=User1,CN=Users,DC=yourdomain,DC=com". This will discover the appropriate domain controller automatically and bind to it to get the object.
- If you're doing a search using DirectorySearcher, and you don't supply a SearchRoot object it will automatically bind to the root of the current domain. You can provide a SearchRoot to narrow down the search but you don't have to.
- If you absolutely need to get the name of the current domain, you can bind to an object called RootDSE ("LDAP://RootDSE") and get the value of the defaultNamingContext attribute. This will return the "DC=yourdomain,DC=com" bit.
Frankly, more general code is probably not worth the pain unless you're sure you're going to need it because it will be dependent on the structure of your domains and forests. E.g. if you have two forests, is there a trust between them: you won't know this until you have two forests and the solution will depend on this. There's a pithy little maxim in agile development which escapes me but it goes along the lines of don't code what you don't need now.
Here's a console program that will perform such a search:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
namespace SearchDirectory
{
class Program
{
static void Main(string[] args)
{
string user = @"YOURDOMAIN\yourid";
using (DirectorySearcher ds = new DirectorySearcher())
{
ds.SearchScope = SearchScope.Subtree;
ds.Filter = String.Format("(&(objectClass=user)(objectCategory=person)(sAMAccountName={0}))",
user.Split('\\')[1]);
ds.PageSize = 1000;
using (SearchResultCollection src = ds.FindAll())
{
foreach (SearchResult sr in src)
Console.WriteLine(sr.Properties["distinguishedName"][0].ToString());
}
}
Console.WriteLine("\r\nPress a key to continue...");
Console.ReadKey(true);
}
}
}
I've cut some corners on this but it should get you started. My advice is to get it working in a console program and then move the class to your ASP.NET project. There are plenty of odd errors System.DirectoryServices can throw you and using S.DS inside of ASP.NET can be fun too so it's best to know your code works before you wrap it in all of that ASP.NET loveliness.