Reputation: 11403
I've been trying to create new local user accounts on windows 7 machine. I used the System.DirectoryServices.DirectoryEntry class (as in here) but it doesn't seem to work.
Here's the code in the article:
static void Main(string[] args)
{
try
{
DirectoryEntry AD = new DirectoryEntry("WinNT://" +
Environment.MachineName + ",computer");
DirectoryEntry NewUser = AD.Children.Add("TestUser1", "user");
NewUser.Invoke("SetPassword", new object[] {"#12345Abc"});
NewUser.Invoke("Put", new object[] {"Description", "Test User from .NET"});
NewUser.CommitChanges();
DirectoryEntry grp;
grp = AD.Children.Find("Guests", "group");
if (grp != null) {grp.Invoke("Add", new object[] {NewUser.Path.ToString()});}
Console.WriteLine("Account Created Successfully");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
When executing this line
DirectoryEntry NewUser = AD.Children.Add("TestUser1", "user");
I get a
System.Runtime.InteropServices.COMException
with "{"Unknown error (0x80005000)"}
"
as the exception message, and -2147463168
as the error code.
I assume this is probably because the article targets Windows XP and below machines, and I'm targeting windows 7 and Windows server 2008.
Any help appreciated!
Update:
For some mysterious reason, i'm no longer seeing that System.Runtime.InteropServices.COMException
, however, when committing the changes here newuser.CommitChanges()
, I get a "UnAuthorizedAccessException
". I tried running the app as administrator, but still not working.
Update 2:
OK, after changing to the UserPrincipal class, i got the follwoing code to work:
public UserPrincipal CreateNewUser(string sUserName, string sPassword)
{
// first check that the user doesn't exist
if (GetUser(sUserName) == null)
{
PrincipalContext oPrincipalContext = GetPrincipalContext();
UserPrincipal oUserPrincipal = new UserPrincipal(oPrincipalContext);
oUserPrincipal.Name = sUserName;
oUserPrincipal.SetPassword(sPassword);
//User Log on Name
//oUserPrincipal.UserPrincipalName = sUserName;
oUserPrincipal.Save();
return oUserPrincipal;
}
// if it already exists, return the old user
return GetUser(sUserName);
}
}
This code runs well when I run it as a console app -of course run as administrator- but when i deployed it as a windows service, with the security account set as "LocalSystem", i get an InvlaidOperationException
saying "The underlying store does not support this property"
Thoughts?
Upvotes: 7
Views: 26726
Reputation: 11403
OK, if you check my last update, the following snippet worked:
public UserPrincipal CreateNewUser(string sUserName, string sPassword)
{
// first check that the user doesn't exist
if (GetUser(sUserName) == null)
{
PrincipalContext oPrincipalContext = GetPrincipalContext();
UserPrincipal oUserPrincipal = new UserPrincipal(oPrincipalContext);
oUserPrincipal.Name = sUserName;
oUserPrincipal.SetPassword(sPassword);
//User Log on Name
//oUserPrincipal.UserPrincipalName = sUserName;
oUserPrincipal.Save();
return oUserPrincipal;
}
// if it already exists, return the old user
return GetUser(sUserName);
}
}
That worked as a console app, but failed to execute due to security exceptions when deployed as a windows service. A solution is to trust that assembly (the windows service assembly) so that the .net security will let it run. That's done, now everything is cool!
Upvotes: 9
Reputation: 3874
You need to prefix your username with CN=, like so:
DirectoryEntry NewUser = AD.Children.Add("CN=TestUser1", "user");
Upvotes: 0