How to search a user that has a letter (or a few) in his display name

I'll try to explain myself better. I'm using C# to build a mini-program to myself. I want to search a user within my active directory, but I want to search a user without a full display name. Let me explain myself. For example, my display name can be: "David Holonka\Jeramy". Is there a way to search the letters "lonka" and it'll find me all the users that has these combinations of letters within their display name?

My current code:

using (var pc = new PrinicpalContext(ContextType.Domain, "MyDomain"))
{
UserPrincipal user = new UserPrinicpal(pc);
User.DisplayName = "Holonka";
PrinicpalSearcher scrh = new PrinicpalSearcher(user);
Prinicpal found = scrh.FindOne();
}

}

Right now it doesn't find anything becasue there isn't a user that its display name is only "Holonka", but I want it to find the user that i've mentioned before

Thank you very much!

2 answers

  • answered 2019-02-03 17:22 Vadim Martynov

    You can use query string in the PrinicpalSearcher:

    UserPrincipal user = new UserPrinicpal(pc);
    User.DisplayName = "*Holonka*";
    PrinicpalSearcher searcher = new PrinicpalSearcher(user);
    var results = searcher.FindAll();
    

    You can also using PrincipalSearcher to find users with “or” parameters like in the example below:

    List<UserPrincipal> searchPrinciples = new List<UserPrincipal>();
    searchPrinciples.Add(new UserPrincipal(context) { DisplayName="*Holonka*"});
    searchPrinciples.Add(new UserPrincipal(context) { SamAccountName = "*Holonka*" });
    searchPrinciples.Add(new UserPrincipal(context) { MiddleName = "*Holonka*" });
    searchPrinciples.Add(new UserPrincipal(context) { GivenName = "*Holonka*" });
    List<Principal> results = new List<Principal>();
    foreach (var item in searchPrinciples)
    {
        var searcher = new PrincipalSearcher(item);
        // Results may contains duplicate values because of separate searchers can handle the same user
        results.AddRange(searcher.FindAll());
    }
    

  • answered 2019-02-03 18:23 Gabriel Luci

    You can also try using Ambiguous Name Resolution, which is a special AD query that looks for partial matches in several attributes (the list of those attributes is in that article).

    You can't use PrincipalSearcher do use ANR though. You have to use DirectorySearcher (which is what PrincipalSearcher uses in the background anyway).

    Here's an example:

    var searchRoot = new DirectoryEntry("LDAP://domain.com");
    var searcher = new DirectorySearcher(searchRoot) {
        Filter = "(anr=Holonka)"
    };
    searcher.PropertiesToLoad.Add("displayName");
    
    using (var results in = searcher.FindAll()) {
        foreach (SearchResult result in results) {
            if (result.Properties.Contains("displayName")) {
                var displayName = (string) result.Properties["displayName"][0];
                //do something else
            }
        }
    }
    

    When using DirectorySearcher, it's wise to use PropertiesToLoad. If you don't, it will return every attribute that has a value, which is likely way more data than you need. It's a waste of network traffic and time.

    The using statement is also wise, since SearchResultCollection can't be completely cleaned up by the garbage collector.

    I wrote some more about that in an article I wrote: Active Directory: Better Performance