Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Faster way to find out if a user exists on a system?

I have an application that checks to see if a user exists (if not create it) every time it starts. This is done as follows:

bool bUserExists = false;
DirectoryEntry dirEntryLocalMachine = 
    new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer");

DirectoryEntries dirEntries = dirEntryLocalMachine.Children;

foreach (DirectoryEntry dirEntryUser in dirEntries)
{
    bUserExists = dirEntryUser.Name.Equals("UserName", 
        StringComparison.CurrentCultureIgnoreCase);

    if (bUserExists)
      break;
}

The problem is on the majority of the systems where it is deployed. This can take 6 - 10 seconds, which is too long ... I need to find a way to reduce this (as much as possible). Is there a better or faster way I can use to verify if a user exists on the system or not?

I know there are other ways to solve this, like have the other applications sleep for 10 seconds, or have this tool send a message when it is ready, etc... But if I can greatly reduce the time it takes to find the user, it would make my life much easier.

like image 559
Shaitan00 Avatar asked Nov 04 '09 18:11

Shaitan00


3 Answers

.NET 3.5 supports new AD querying classes under the System.DirectoryServices.AccountManagement namespace.

To make use of it, you'll need to add "System.DirectoryServices.AccountManagement" as a reference AND add the using statement.

using System.DirectoryServices.AccountManagement;


using (PrincipalContext pc = new PrincipalContext(ContextType.Machine))
{
    UserPrincipal up = UserPrincipal.FindByIdentity(
        pc,
        IdentityType.SamAccountName,
        "UserName");

    bool UserExists = (up != null);
}

< .NET 3.5

For versions of .NET prior to 3.5, here is a clean example I found on dotnet-snippets

DirectoryEntry dirEntryLocalMachine =
    new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer");

bool UserExists =
    dirEntryLocalMachine.Children.Find(userIdentity, "user") != null;
like image 166
Michael La Voie Avatar answered Nov 08 '22 01:11

Michael La Voie


You want to use the DirectorySearcher.

Something like this:

static bool userexists( string strUserName ) {
    string adsPath = string.Format( @"WinNT://{0}", System.Environment.MachineName );
    using( DirectoryEntry de = new DirectoryEntry( adsPath ) ) {
        try {
            return de.Children.Find( strUserName ) != null;
        } catch( Exception e ) {
            return false;
        }
    }
}

That should be quicker. Also, you can reduce the properties if all you are doing is checking for existence.

like image 26
Beached Avatar answered Nov 08 '22 02:11

Beached


Another way is the following (supports either local or domain user):

bool UserExists(string userName)
{
    var user = new NTAccount(userName);
    try
    {
        var sid = (SecurityIdentifier)user.Translate(typeof(SecurityIdentifier));
        return true;
    }
    catch (IdentityNotMappedException)
    {
        return false;
    }
}

User may be either unqualified, or qualified by machine/domain name (DOMAIN\UserName). If you need to specifically detect if the account exists on local machine, qualify it by Environment.MachineName ($"{Environment.MachineName}\\{userName}").

like image 23
Mike Rosoft Avatar answered Nov 08 '22 02:11

Mike Rosoft