I'm struggling a bit with my simple console-du开发者_开发百科mp-program. I connect to AD using
DirectoryEntry entry =
new DirectoryEntry("LDAP://" + domain, username, password);
and from there I recursively loop thru every child by
foreach (DirectoryEntry child in entry.Children)
{
Traverse(child);
}
Then I start getting mambo jambo data, users popping up more then once and null objects so I wonder if the way I handle the AD that it is just a handle and not a copy so its not loaded completely when I start traversing it?
Any tips/pointers on what to do?
If you can, move up to .NET 3.5 and use the new System.DirectoryServices.AccountManagement
namespace - much easier to use.
See: Managing Directory Security Principals in the .NET Framework 3.5
Also: you need to understand Active Directory isn't just a flat list of users and groups - it's a hierachical system of OU's (organizational units) that can be nested into one another, and can contain users, groups, computers and more.
So what exactly do you want to do?? Get the users for a given OU (e.g. "Sales")?? Or really get all users from your AD?? You do understand this could take quite a while, depending on the size of your company's AD.......
If you really want to get ALL users and ALL groups from your entire AD - you should probably set up a DirectorySearcher
at the root level:
// set search root
DirectoryEntry deRoot = new DirectoryEntry("LDAP://dc=YourCompany,dc=com");
// declare directory searcher
DirectorySearcher dsUsers = new DirectorySearcher(deRoot);
// scope is full subtree, filter defines to search for users
dsUsers.SearchScope = SearchScope.SubTree;
dsUsers.Filter = "(objectCategory=person)";
// define what properties you want to have loaded into your search results
dsUsers.PropertiesToLoad.Add("givenName");
dsUsers.PropertiesToLoad.Add("surname");
dsUsers.PropertiesToLoad.Add("samAccountName");
// loop through results of search
foreach(SearchResult result in dsUsers.FindAll())
{
if(result.Properties["givenName"] != null)
string givenName = result.Properties["givenName"][0].ToString();
if(result.Properties["surname"] != null)
string surname = result.Properties["surname"][0].ToString();
if(result.Properties["sAMAccountName"] != null)
string samAccountName = result.Properties["sAMAccountName"][0].ToString();
}
When reading out the properties of your SearchResult
, you need to check to make sure you did actually get a value back - otherwise your assignment will crash and burn....
For the groups, just use this filter instead:
dsUsers.Filter = "(objectCategory=group)";
If you can narrow your search, e.g. to a given OU, you can get much better performance, since the search tree gets smaller and thus the search would be a lot faster. To do so, just define a different LDAP path for your deRoot
directory entry (e.g. LDAP://OU=Sales,DC=YourCOmpany,DC=com
or whatever OU you want to search in).
Update: as I said - with .NET 3.5, it gets a lot easier still! You need to add a reference to System.DirectoryServices.AccountManagement
, and then you can use code something like this using a sort of "query-by-example" approach:
// create a domain context for the current domain
PrincipalContext domain = new PrincipalContext(ContextType.Domain);
// create a principal object decsribing what to search for
UserPrincipal user = new UserPrincipal(domain);
user.IsActive = true;
// create a principal searcher for running a search operation
PrincipalSearcher searcher = new PrincipalSearcher(user);
// run the query
PrincipalSearchResult<Principal> results = searcher.FindAll();
// iterate over all results
foreach (Principal result in results)
{
Console.WriteLine("name: {0}", result.Name);
}
And for searching for groups, just instantiate a GroupPrincipal
, set any properties on it and then pass that into the PrincipalSearcher
to search for groups.
精彩评论