views:

914

answers:

3

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;
}

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). So 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 he is ready, etc... but if I can greatly reduce the time it takes to find the user it would make my life much easier.

Any help would be greatly appreciated. Thanks,

+5  A: 

.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;
Michael La Voie
Sadly I cannot use .NET 3.5, I am stuck with .NET 2.0...Is there an equivalent?
Shaitan00
I updated my answer to include a great article on exactly what you're looking for. It is very similar to your current method, but instead of enumerating through every object, it uses the Children.Find() function. Please click the link as the article has a complete class to handle this and it is very nice.
Michael La Voie
It works - but takes just as long ...
Shaitan00
:( - That's too bad and I don't know any other solutions that weren't mentioned. Of course, you could re-evaluate whether that logic needs to be called every time or if it needs to be called on start up. Perhaps put it in a thread to let the user start working? Otherwise, perceptions play a big role, showing a progress bar with an exponential acceleration (ie: slow for 2 sec, medium speed for 2 sec, then super fast for last two) can create the perception of fast loading. If all else fails, try this:http://stackoverflow.com/questions/182112/funny-loading-statements-to-keep-users-amused
Michael La Voie
A: 

The following in a command prompt returns 1 if 'username' exists.

net user | find "username" /c

kenny
What does that have to do with finding out if a user exists in C#?
Ken White
It could be used by C#, but im afraid this is not the most neat solution.
Henri
I do not want to start spawning command shells to use net user, something with C# would be better.
Shaitan00
@Henri: OK, you can use it. How do you get the results in your C# app to find out if the user exists? Post the code, please.
Ken White
+3  A: 

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 existance.

Beached
This is a fast method AND it works with .NET versions prior to 3.5 (if that is your environment).
Michael La Voie
Where is result set?
Shaitan00
I'm not that familiar with DirectoryEntry (active directory and stuff), which properties are not needed to be 100% certain the user does not already exist if I only have the UserName to go by?
Shaitan00
Actually, don't include any and it should be fine. I was just giving a generic example in case you wanted info on them too. So the filter is what you want and then the searchresult.
Beached
Beached: There are a couple of issues with that snipplet of code, for example string strDomainName uses ds but ds is created later and uses de which ises strDomainName (cyclic issue)...
Shaitan00
I was wrong about DirectorySearcher. It only works with AD. I have updated the solution to use the Find method on the DirectoryEntry object.
Beached