tags:

views:

5139

answers:

5

How can I create a local user account using .NET 2.0 and c# and also be able to set the "Password never expires" to never.

I have tried using "Net.exe" using Process.Start and passing its parameters but it seems that the "net user" is unable to set the "Password never expires" to never.

+8  A: 

Read this excellent CodeProject article

Howto: (Almost) Everything In Active Directory via C#

There is a section "Create User Account" and "Dealing with User Passwords".

UPDATE:

To adapt the code for local accounts replace the respective lines with these:

DirectoryEntry localMachine = new DirectoryEntry("WinNT://" + 
    Environment.MachineName);
DirectoryEntry newUser = localMachine.Children.Add("localuser", "user");

Here starts the original code snippet for domain accounts:

public string CreateUserAccount(string ldapPath, string userName, 
    string userPassword)
{
    try
    {
        string oGUID = string.Empty;
        string connectionPrefix = "LDAP://" + ldapPath;
        DirectoryEntry dirEntry = new DirectoryEntry(connectionPrefix);
        DirectoryEntry newUser = dirEntry.Children.Add
            ("CN=" + userName, "user");
        newUser.Properties["samAccountName"].Value = userName;

        int val = (int)newUser.Properties["userAccountControl"].Value; 
        newUser.Properties["userAccountControl"].Value = val | 0x10000; 

        newUser.CommitChanges();
        oGUID = newUser.Guid.ToString();

        newUser.Invoke("SetPassword", new object[] { userPassword });
        newUser.CommitChanges();

        dirEntry.Close();
        newUser.Close();
    }
    catch (System.DirectoryServices.DirectoryServicesCOMException E)
    {
        //DoSomethingwith --> E.Message.ToString();

    }
    return oGUID;
}

There are some specifics to understand when dealing with user passwords and boundaries around passwords such as forcing a user to change their password on the next logon, denying the user the right to change their own passwords, setting passwords to never expire, to when to expire, and these tasks can be accomplished using UserAccountControl flags that are demonstrated in the proceeding sections.

Please refer to this great MSDN article: Managing User Passwords for examples and documentation regarding these features.

CONST                          HEX
------------------------------------------
SCRIPT                         0x0001
ACCOUNTDISABLE                 0x0002
HOMEDIR_REQUIRED               0x0008
LOCKOUT                        0x0010
PASSWD_NOTREQD                 0x0020
PASSWD_CANT_CHANGE             0x0040
ENCRYPTED_TEXT_PWD_ALLOWED     0x0080
TEMP_DUPLICATE_ACCOUNT         0x0100
NORMAL_ACCOUNT                 0x0200
INTERDOMAIN_TRUST_ACCOUNT      0x0800
WORKSTATION_TRUST_ACCOUNT      0x1000
SERVER_TRUST_ACCOUNT           0x2000
DONT_EXPIRE_PASSWORD           0x10000
MNS_LOGON_ACCOUNT              0x20000
SMARTCARD_REQUIRED             0x40000
TRUSTED_FOR_DELEGATION         0x80000
NOT_DELEGATED                  0x100000
USE_DES_KEY_ONLY               0x200000
DONT_REQ_PREAUTH               0x400000
PASSWORD_EXPIRED               0x800000
TRUSTED_TO_AUTH_FOR_DELEGATION 0x1000000
splattne
The links you specified is for active directory. Maybe I wasn't clear. I want to change local user account (The computer is not part of an active directory).
Mohammadreza
As far as I remember it should apply to local accounts too.
splattne
@ Mohammadreza : I updated my answer. Now there is code which handles local accounts
splattne
A: 

Can you grab addusers.exe from the resource kit?

http://www.ss64.com/nt/addusers.html

kenny
+6  A: 

This code will create a local account with the password never expires option set:

        using System.DirectoryServices;

        DirectoryEntry hostMachineDirectory = new DirectoryEntry("WinNT://localhost");
        DirectoryEntries entries = hostMachineDirectory.Children;
        bool userExists = false;
        foreach (DirectoryEntry each in entries)
        {
            userExists = each.Name.Equals("NewUser",  
            StringComparison.CurrentCultureIgnoreCase);
            if (systemtestUserExists)
                break;
        }

        if (false == userExists)
        {
            DirectoryEntry obUser = entries.Add("NewUser", "User");
            obUser.Properties["FullName"].Add("Local user");
            obUser.Invoke("SetPassword", "abcdefg12345@");
            obUser.Invoke("Put", new object[] {"UserFlags", 0x10000});
            obUser.CommitChanges();
        }

The 0x10000 flag means PasswordNeverExpires.

I spent a long time figuring out how to create a local user account with the password set not to expire. It seems that when you try to use:

int val = (int)newUser.Properties["userAccountControl"].Value; 
newUser.Properties["userAccountControl"].Value = val | 0x10000

permissions from active directory come into play. If you have active directory permissions everything works fine. If you don't then getting the userAccountControl property will always result in a null value. Trying to set userAccountControl will result in an exception "The directory property cannot be found in the cache".

However after much hunting around I found another property "UserFlags" that needs to be set using Invoke. You can use this to set the flag on a local account. I've tried this code and it worked on windows server 2008.

Hope this helps

Ed Sykes
Nice one, +1. A couple of notes: first, DirectoryEntry is disposable, so better wrap with a using {}; second, the DirectoryEntry constructor can take a remote machine name if you need to create a local user on a remote box.
Jeremy McGee
+1  A: 

Thanks Ed Sykes, you saved me a lot of digging around :) I was facing the same problem. Only problem left now, is that i cant invoke the never expires in combination with the cant change password (0x0040) flag.. (disables 1 of both flags).. But probably i will find a cure for that issue later ;)

Raymond Fraikin
Sweet, found it :) // To save some of you out there the trouble:newUser.Invoke("Put", new object[] { "UserFlags", 0x10000 + 0x0040 });
Raymond Fraikin
A: 

Thank for your code. It helps me much

researcher