« Creating Groups in Active Directory with PowerShell | Main | Managing group membership in Active Directory with PowerShell (Part 1) »
Creating a User Account in Active Directory with PowerShell
By Adam Bell | February 14, 2007
There are a lot of attributes that can set when creating a User in AD. I’m not going to display them all here, but if you’re interested in what can be set (on any AD object) I recommend using ADSIedit which is included with the Windows Support Tools shipped on the Windows Server disc.
It’s worth mentioning here that this is a very powerful tool. It doesn’t wrap you in wool while you’re wandering around your Active Directory. You can really screw it up if you’re not careful. I would therefore strongly advise that you use this tool on a development environment where a mistake is less likely to get you fired ;)
Microsoft have an overview of ADSIedit here.
Below is the function to create an account, and then we’ll step through some points of interest.
new-account.ps1
# Constants from: http://msdn2.microsoft.com/en-us/library/aa772300.aspx
Set-Variable -Name ADS_UF_ACCOUNT_DISABLE -value 0x2 -option constant
Set-Variable -Name ADS_UF_DONT_EXPIRE_PASSWORD -value 0x10000 -option constant
Set-Variable -Name ADS_UF_PASSWORD_EXPIRED -value 0x800000 -option constant
$rootdn = ([adsi]"").distinguishedName
# ---------------------------------------------------------------------------------------------------
function Convert-DNtoFQDN
# ---------------------------------------------------------------------------------------------------
{
Param (
$DNname
)
$FQDN = $null
$bits = $DNname.split(",")
# Put each section back together again with the period in place.
foreach ($part in $bits)
{
$a = $part.split("=")
$FQDN = $FQDN+$a[1]+"."
}
# Need to drop the trailing dot from the end.
$FQDN = $FQDN.substring(0,$FQDN.length -1)
return $FQDN
}
# ---------------------------------------------------------------------------------------------------
function create-account
# ---------------------------------------------------------------------------------------------------
{
# Depends on Convert-DNtoFQDN function
Param (
$Location,
$User,
$Desc = $null,
$Password = $null
)
# If a password isn't provided use this one.
$DefaultPass = "LetM3In"
$ou = [adsi]("LDAP://"+$Location+","+$rootdn)
$newuser = $ou.create("user", "cn="+$User)
$newuser.Put("sAMAccountName", $User)
if ($Desc -ne $null) { $newuser.Put("Description", $desc) }
# Build the UPN based on the $rootdn value.
$newuser.Put("userPrincipalName", $User+"@"+(Convert-DNtoFQDN $rootDn.ToString()))
$newuser.SetInfo()
If ($Password -ne $null)
{
$newuser.psbase.invoke("setpassword", $Password)
}
else
{
$newuser.psbase.invoke("setpassword", $DefaultPass)
}
$newuser.SetInfo()
# Enable the account
$newuser.psbase.invokeset('accountdisabled', $false)
# a value of 0 effectively ticks the "User must change password at next logon"
# box. A value of -1 clears this tick.
$newuser.PwdLastSet = 0
$newuser.Setinfo()
# When manipulating UAC bits, you need to OR them to the existing UAC flag to enable them
# and AND (NOT) them to remove them. Or you can just write the bitwise number to the attribute...
$uacFlag = $newuser.userAccountControl
$newflag = $uacFlag[0] -bor $ADS_UF_DONT_EXPIRE_PASSWORD
$newuser.userAccountControl = $newflag
$newuser.setinfo()
}
This function can be called in several ways. Due to defining default values for two of the variables we can call it with:
create-account "ou=Test OU" "BellA" "Adam's Test Account" "Password12"
Or we could just use:
create-account "ou=Test OU" "BellA"
And the default password will be used.
The caveat here is that the password must conform to the password requirements for the domain!. Otherwise the function will be successful, however the password will not work when you try and logon.
The last thing to note is that the last two code blocks actually conflict with each other. You cannot set the account to require a password change on next logon, and set the password doesn’t expire bit. If you attempt this through Active Directory Users and Computers, the following dialog is displayed:
With the code blocks above the PwdLastSet attribute is set, however it’s overwritten by the UAC flag setting.
This is quite a simple example of creating an account. We have only set some of the mandatory attributes. There is no first (givenName) and surname (sn) defined. I’ll show you in another post how to retrieve the attributes from the User class. In the mean time ADSIedit provides a simple interface for browsing what’s available.
- Creating Groups in Active Directory with PowerShell
- Managing group membership in Active Directory with PowerShell (Part 1)
- Managing group membership in Active Directory with PowerShell (Part 2)
- Active Directory Permissions – Standard Rights
- Creating an Organizational Unit in Active Directory with PowerShell
Topics: Active Directory, PowerShell | 5 Comments »
February 16th, 2007 at 7:03 pm
I’ve built a similar script to create user accounts. My big question is: have you attempted to tackle setting up home folders? As far as I can tell, doing that in PowerShell is uncharted territory. Anyway, your user creation script is way nicer than mine :)
February 16th, 2007 at 9:41 pm
Nevermind, I found the solution in pure C# and adapted it for my full-user-setup script. Feel free to do…whatever…with it.
1. Link/citing source: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1204480&SiteID=1
2. Calling lines of code:
#—————-
CreateHomeDirectory $username
$u.put(“homeDirectory”, $homeDirectory)
$u.put(“homeDrive”, $homeDrive)
$u.setInfo()
#——————–
3. Function:
#———————
function CreateHomeDirectory
{
param([string]$username)
trap
{
write-host “ERROR on account: $username”
write-host “ID: ” $_.ErrorID
write-host “Message: “$_.Exception.Message
break
}
$folderpath = “{0}{1}” -f $USER_ROOT_UNC, $username
$folder = get-item $folderpath -ErrorAction SilentlyContinue
if (-not $folder)
{
#see http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1204480&SiteID=1
#this explains why you need to set three rules for one user.
$folder = new-item $folderpath -itemtype directory -ErrorAction Stop
#InheritanceFlags.ObjectInherit = 2
#PropogationFlags.InheritOnly = 2
$ar1 = new-object System.Security.AccessControl.FileSystemAccessRule($username,”FullControl”,2,2,”Allow”)
#InheritanceFlags.ContainerInherit = 1
#PropogationFlags.InheritOnly = 2
$ar2 = new-object System.Security.AccessControl.FileSystemAccessRule($username,”FullControl”,1,2,”Allow”)
$ar3 = new-object System.Security.AccessControl.FileSystemAccessRule($username,”FullControl”,”Allow”)
$acl = get-acl $folder
$acl.AddAccessRule($ar1)
$acl.AddAccessRule($ar2)
$acl.AddAccessRule($ar3)
set-acl $folder $acl -ErrorAction Stop
}
else
{
#ERROR.
#home directory shouldn’t already exist for a brand new user.
#this is a potential collision – need to manually resolve.
throw “user: $username – already has home directory of the same name.”
}
}
March 12th, 2007 at 6:41 pm
Yeargh, my above function is giving me problems today, I’d like to retract this from the internet in general until I figure it out :)
July 17th, 2007 at 1:11 pm
I used the following code to convert DN to FQDN:
#get the DN
$rootDSE = [ADSI]“LDAP://RootDSE”
$domainDN = $rootDSE.Get(“DefaultNamingContext”)
#convert the DN to FQDN
$domainFQDN = $domainDN -replace(“,dc=”,”.”) -replace(“dc=”,”")
July 17th, 2007 at 1:17 pm
Hi Briano,
Nice way of doing it. I wrote a function (see sample code page) that does the same thing, but isn’t as elegant.
It was something I wrote early on playing with PoSH, and so is VBScript centric. I like your PoSH way much better.
Time to ferret out the library file and update it ;)
Thanks for the comment.
Cheers
Adam