Last time I wrote about how you can reach the Active Directory search dialog in Windows 7. Today I’ll show you how to search comfortable for users in the Active Directory by using C#. The emphasis is on comfort, because there are quite a few articles on the subject in general, on the internet.
However, most of the shown methods/solutions are build exclusively around System.DirectoryServices.ActiveDirectory and the DirectorySearcher. But ever since .NET 3.5 it is also possible to search in the Active Directory much easier.
But let us come to the point. In the following example, I mostly use methods from the System.DirectoryServices.AccountManagement namespace. And here’s how:
//Create a shortcut to the appropriate Windows domain PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, "myDomain"); //Create a "user object" in the context UserPrincipal user = new UserPrincipal(domainContext); //Specify the search parameters user.Name = "he*"; //Create the searcher //pass (our) user object PrincipalSearcher pS = new PrincipalSearcher(); pS.QueryFilter = user; //Perform the search PrincipalSearchResult<Principal> results = pS.FindAll(); //If necessary, request more details Principal pc = results.ToList()[0]; DirectoryEntry de = (DirectoryEntry)pc.GetUnderlyingObject(); //Output first result of the test MessageBox.Show(de.Properties["mail"].Value.ToString());
After you’ve now seen the source code, there are of course a few more notes to it. In line 9, I set the Name property of user. The * is seen as a wildcard. It would be in line 17 all Active Directory user entries returned whose name starts with “he”.
Basically, it has to be said, that you can search for many other properties, instead of the Name property set, which then act as filters. Also, the combining of a plurality of properties is possible.
No products found.
Also, I would like to mention, that from line 21 on, all code is optional. In most cases, the principal objects contain all the data you need to know. However, these principal objects do not contain all properties that can be set as in the Active Directory.Should you are searching an actual shaft that does not grasp the principal object, so you have to fall back on the old way method, raised at the beginning of this article.
always wrap the resources in using()’s
see:
https://docs.microsoft.com/en-us/dotnet/api/system.directoryservices.searchresultcollection#remarks
Hi
Is there a way we can use multiple filter like an OR clause, similar to (!(attribute1 = value)(attribue2=value)) using principal searcher query filter.
Thanks, it helped me.
Gracias, excelente publicación.
Hi,
I’m new in writing code to access AD. Recetnly, my company setup a new AD server with the structue similiar to follows:
DC=UAT,DC=COM
OU=ORG
OU=Servers
OU=Services Accounts
OU=Users and Groups
OU=System
OU=Groups
CN=Admins
OU=Users
OU=Test
OU=Groups
OU=Users
CN=test01
CN=test02
OU=XXX
OU=Groups
OU=Users
CN=XXX01
CN=XXX02
I need to write an application to search a user and then change the password and also implement other functions.
But my first task to seach an user to change the password is failed.
I wrote the following sample codes to search for the user:
using System;
using System.IO;
using System.DirectoryServices;
using System.Configuration;
try
{
DirectoryEntry userEntry = new DirectoryEntry(“LDAP://SERVERIP/OU=Users and Groups,OU=ORG,DC=UAT,DC=COM”, null, null, AuthenticationTypes.ServerBind | AuthenticationTypes.FastBind);
DirectorySearcher search = new DirectorySearcher(userEntry);
search.SearchScope = SearchScope.Subtree;
search.ReferralChasing = ReferralChasingOption.All;
// Search user test02
search.Filter = “(&(objectClass=user)(objectCategory=Person)(sAMAccountName=test02))”;
SearchResult result = search.FindOne(); // Failed at this line, throw exception
if (result == null)
Console.WriteLine(“There is no results to display”);
else
Console.WriteLine(“Found result “);
}
catch (Exception ex)
{
Console.WriteLine(“Error: ” + ex.Message);
Console.WriteLine(“Trece: ” + ex.StackTrace);
}
Error: Configuration system failed to initialize
Trece: at System.Configuration.ClientConfigurationSystem.EnsureInit(String configKey)
at System.Configuration.ClientConfigurationSystem.PrepareClientConfigSystem(String sectionName)
at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName)
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at System.Configuration.PrivilegedConfigurationManager.GetSection(String sectionName)
at System.DirectoryServices.SearchResultCollection.ResultsEnumerator..ctor(SearchResultCollection results, String parentUserName, String parentPassword, AuthenticationTypes parentAuthenticationType)
at System.DirectoryServices.SearchResultCollection.GetEnumerator()
at System.DirectoryServices.DirectorySearcher.FindOne()
Could you help and advise what I did wrong?
Thank you very much!
Lwang
It’s important to note that you should wrap PrincipalContext, UserPrincipal, PrincipalSearcher and PrincipalSearchResult in using statements or to dispose of them when you’re done. All of these use unmanaged code on the backend and you’ll end up with a memory leak if you don’t properly deal with them.
Thanks for the advice!