tags:

views:

973

answers:

1

What is the simplest and most efficient way in C# to check if a Windows user account name exists? This is in a domain environment.

  • Input: user name in [domain]/[user] format (e.g. "mycompany\bob")
  • Output: True if the user name exists, false if not.

I did find this article but the examples there are related to authenticating and manipulating user accounts, and they assume you already have a user distinguished name, whereas I am starting with the user account name.

I'm sure I can figure this out using AD, but before I do so I was wondering if there is a simple higher level API that does what I need.

* UPDATE *

There are probably many ways to do this, Russ posted one that could work but I couldn't figure out how to tweak it to work in my environment. I did find a different approach, using the WinNT provider that did the job for me:

    public static bool UserInDomain(string username, string domain)
    {
        string path = String.Format("WinNT://{0}/{1},user", domain, username);

        try
        {
            DirectoryEntry.Exists(path);
            return true;
        }
        catch (Exception)
        {
            // For WinNT provider DirectoryEntry.Exists throws an exception
            // instead of returning false so we need to trap it.
            return false;
        }
    }

P.S. For those who aren't familiar with the API used above: you need to add a reference to System.DirectoryServices to use it.

The link I found that helped me with this: How Can I Get User Information Using ADSI The examples use ADSI but can be applied to .NET DirectoryServices as well. They also demonstrate other properties of the user object that may be useful.

+2  A: 

The System.DirectoryServices namespace in the article is exactly what you need and intended for this purpose. If I recall correctly, it is a wrapper around the Active Directory Server Interfaces COM interfaces

EDIT:

Something like the following should do it (it could probably do with some checking and handling). It will use the domain of the current security context to find a domain controller, but this could easily be amended to pass in a named server.

public bool UserInDomain(string username, string domain)
{
    string LDAPString = String.Empty;
    string[] domainComponents = domain.Split('.');
    StringBuilder builder = new StringBuilder();

    for (int i = 0; i < domainComponents.Length; i++)
    {
        builder.AppendFormat(",dc={0}", domainComponents[i]);
    }
    if (builder.Length > 0)
        LDAPString = builder.ToString(1, builder.Length - 1);

    DirectoryEntry entry = new DirectoryEntry("LDAP://" + LDAPString);

    DirectorySearcher searcher = new DirectorySearcher(entry);

    searcher.Filter = "sAMAccountName=" + username;

    SearchResult result = searcher.FindOne();

    return (result != null) ? true : false;
}

and tested with the following

Console.WriteLine(UserInDomain("username","MyDomain.com").ToString());
Russ Cam
Those are general purpose APIs for accessing Active Directory information (like ADO.NET for SQL data). The challenge of AD programming is understanding the schema and constructing the right queries to get the information you need (and there is a ton of information stored in AD).
DSO
@DSO - you have the domain and the username, so you should be able to use a DirectorySearcher object to find if the username exists in that domain by instantiating the DirectorySearcher object and passing in a DirectoryEntry object bound to the node representing the domain object
Russ Cam
Your example didn't work for me, I get a "server returned a referral" error, which I think means the container does not exist. I think you're right in principle, to first bind to correct container then searching for the object, so I gave you upvote for that. However I don't think your approach to constructing the query to bind to the domain will work in all environments. I found a simpler solution (updated post).
DSO
I did test it before posting and it worked for me. Did you pass in the fully qualified username for username or just the username? Only the username will work
Russ Cam