views:

2495

answers:

2

I need to create a new user in Active Directory. I have found several examples like the following:

using System;
using System.DirectoryServices;

namespace test {
   class Program {
      static void Main(string[] args) {
        try {
            string path = "LDAP://OU=x,DC=y,DC=com";
            string username = "johndoe";

            using (DirectoryEntry ou = new DirectoryEntry(path)) {
               DirectoryEntry user = ou.Children.Add("CN=" + username, "user");

               user.Properties["sAMAccountName"].Add(username);

               ou.CommitChanges();
            }
         } 
         catch (Exception exc) {
             Console.WriteLine(exc.Message);
         }
      }
   }
}

When I run this code I get no errors, but no new user is created.

The account I'm running the test with has sufficient privileges to create a user in the target Organizational Unit.

Am I missing something (possibly some required attribute of the user object)?

Any ideas why the code does not give exceptions?

EDIT
The following worked for me:

int NORMAL_ACCOUNT = 0x200;
int PWD_NOTREQD = 0x20;
DirectoryEntry user = ou.Children.Add("CN=" + username, "user");
user.Properties["sAMAccountName"].Value = username;
user.Properties["userAccountControl"].Value = NORMAL_ACCOUNT | PWD_NOTREQD;
user.CommitChanges();

So there were actually a couple of problems:

  1. CommitChanges must be called on user (thanks Rob)
  2. The password policy was preventing the user to be created (thanks Marc)
+2  A: 

Assuming your OU path OU=x,DC=y,DC=com really exists - it should work :-)

Things to check:

  • you're adding a value to the "samAccountName" - why don't you just set its value:

    user.Properties["sAMAccountName"].Value = username;

    Otherwise you might end up with several samAccountNames - and that won't work.....

  • you're not setting the userAccountControl property to anything - try using:

    user.Properties["userAccountControl"].Value = 512; // normal account

  • do you have multiple domain controllers in your org? If you, and you're using this "server-less" binding (not specifying any server in the LDAP path), you could be surprised where the user gets created :-) and it'll take several minutes up to half an hour to synchronize across the whole network

  • do you have a strict password policy in place? Maybe that's the problem. I recall we used to have to create the user with the "doesn't require password" option first, do a first .CommitChanges(), then create a powerful enough password, set it on the user, and remove that user option.

Marc

marc_s
+4  A: 

I think you are calling CommitChanges on the wrong DirectoryEntry. In the MSDN documentation (http://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentries.add.aspx) it states the following (emphasis added by me)

You must call the CommitChanges method on the new entry to make the creation permanent. When you call this method, you can then set mandatory property values on the new entry. The providers each have different requirements for properties that need to be set before a call to the CommitChanges method is made. If those requirements are not met, the provider might throw an exception. Check with your provider to determine which properties must be set before committing changes.

So if you change your code to user.CommitChanges() it should work, if you need to set more properties than just the account name then you should get an exception.

Since you're currently calling CommitChanges() on the OU which hasn't been altered there will be no exceptions.

RobV
Good catch !! :-)
marc_s
the power of reading "manuals" in action :)
balexandre