Adding Users through PowerShell

Now that we have our OU structure in place, we can start adding users.

Since the Users contain alot of information we’ll go ahead and use the whole csv file.

Let’s take a quick look at the first entry in the Csv file:


PS > (Import-Csv StarTrek.csv)[0]


Character  : Jean-Luc Picard
Position   : Commanding Officer
Rank       : Captain
Department : Main Bridge
Species    : Human
Starship   : USS Enterprise (NCC-1701-D)
Class      : Galaxy
Registry   : NCC-1701-D
Series     : Star Trek: The Next Generation
Location   : Alpha Quadrant

Let’s start adding the Users to the Domain. First off, we need to build up a connectionstring. In the script, I build it based on


PS > $Series = "Star Trek: The Next Generation"
PS > $Domain = "powershell.nu"
PS > $Connection = $Series.Insert(0,"LDAP://OU=Users,OU=") + ($Domain.Replace(".",",DC=")).Insert(0,",DC=")
PS > $Connection

LDAP://OU=Users,OU=Star Trek: The Next Generation,DC=powershell,DC=nu

Now for the Fun part. In the Csv file, some Characters don’t have any surNames and some have middle names, so this is something I have to consider in the script. Thanks to the Power of PowerShell it doesn’t have to get to complex.

Step one is Checking the characters name. I use the Split() method to determine if the user has a SurName or any Middle Names.


PS > $Character = "Jean-Luc Picard"
PS > $CharacterName = $Character.Split(" ")
PS > $CharacterName

Jean-Luc
Picard

In this example, Jean-Luc would be the givenName and Picard the surName. I control this in the script through a if else statement that checks if the $CharacterName contains 1 row or more.


if (($CharacterName.Count) -le 1) {

} else {

}

In the case of Jean-Luc Picard, the Name contains more than 1 row, so let’s move on to the else statement.

The else statement starts of by setting up giveName and SurName. the $giveName variable contain all names except the last one. So if we would use Charles Trip Tucker instead of Picard, the givenName would be “Charles Trip” and surName would be set to “Tucker”.


PS > $givenName = $CharacterName[0..($CharacterName.Count -2)]
PS > $sn = $CharacterName[($CharacterName.Count -1)]
PS > $givenName

Jean-Luc

PS > $sn

Picard

Now that we’ve sliced and diced the characters name, we do an additional check to see if the character name will fit the sAMAccountName structure decided in Part 1.0.0 (First 3 from giveName and first 3 from surName).


if ($givenName.Length -lt 3 -AND $sn.Length -lt 3) {

   $Tempcn = $givenName + $sn
   $AddNum = 3 - $Tempcn.Length

   # Build Last Part Of cn

   for ($i = 0; $i -lt ($AddNum -1); $i ++) { $AddTocn += "0" }
   $AddTocn += "1"

   [string]$sAMAccountName = ($Tempcn).ToLower() + $Addtocn
   $cn = $givenName

   # Set Checker to Null

   $AddTocn = $Null

} elseif ($givenName.Length -lt 3 -OR $sn.Length -lt 3) {

   $Tempcn = $givenName + $sn

   [string]$sAMAccountName = ($Tempcn.SubString(0,6)).ToLower()
   $cn = $givenName + " " + $sn

} else {

   [string]$sAMAccountName = ($givenName.SubString(0,3)).ToLower() + ($sn.SubString(0,3)).ToLower()
   $cn = $givenName + " " + $sn
}

The if elseif else statement goes through the characters name and checks if it falls within parameters. If it does not, a number will be added at the end of the Name to compensate. The elseif statement takes care of users where givenName or surName has less than 3 characters and compensates this.

Here’s how Jean-Luc Picard is set up now:


PS > $givenName

Jean-Luc

PS > $sn

Picard

PS > $sAMAccountName

jeapic

PS > $cn

Jean-Luc Picard

Now that we have the sAMAccountName in place we have to check if the sAMAccountName is taken by some other User. We can do this by creating a function that looks up the users sAMAccountName from the Get-AD.ps1 script.


function Check-sAMAccountName ([string]$Domain, [string]$User) {

   trap {  $Script:sAMAccountNameDoesntExist = $True ; continue }
   .Get-AD.ps1 -Domain $Domain -User $User -Filter sAMAccountName | Out-Null
}

If the UserName already exists the script uses a While loop to determine how many sAMAccountNames are taken and when an empty sAMAccountName is found it will be used.


if ($sAMAccountNameDoesntExist -eq $True) {

} else {

   While ($Script:sAMAccountNameDoesntExist -eq $False) {

    $LastChar = $sAMAccountName.SubString($sAMAccountName.Length -1)

    if(1..9 -Contains $LastChar) {

       $sAMAccountName = ($sAMAccountName.TrimEnd([string]$LastChar)) + ([int]$LastChar + 1)
    } else {

       $sAMAccountName = $sAMAccountName + 1
    }

    Check-sAMAccountName -Domain $Domain -User $sAMAccountName
   }
}

If jeapic already exists the number 1 will be appended to his sAMAccountName, and if jeapic1 already exists 1+1 ( 2) would be appended instead. Note that doing this sets the sAMAccountName to 7 characters instead of 6. If you always want to use 6 chars you could substring() out characters 1 to 5 ( 0,4 ) and build up a sAMAccountName containing only 6 characters.

Now that we have a unique sAMAccountName, we want to check the Users distinguishedName. If the distinguishedName already exists then we will not Add the User, since he already exists. If not, we will go ahead and add our user. The distinguishedName check function is basically the same as the sAMAccountName checker, only differens is that it filters on distinguishedName instead.


function Check-distinguishedName ([string]$Domain, [string]$User) {
   trap {  $Script:distinguishedNameDoesntExist = $True ; continue }
   .Get-AD.ps1 -Domain $Domain -User $User -filter distinguishedName | Out-Null
}

The function takes distinguishedName as an argument, so we have to build up this string. The OU structure was set up in Part 1.1.1 so the User should be in the following OU: “OU=Users,OU=Star Trek: The Next Generation,DC=powershell,DC=nu”.


$distinguishedName = "CN=" + $cn + ",OU=Users,OU=" + $Series + ($Domain.Replace(".",",DC=")).Insert(0,",DC=")

If the disyinguishedName doesnt exist, we can go ahead and create the User. For safety reasons, we generate a secure password for each user that we create and store the passwords in a password file. We could obviously set all Passwords to “Password1″ but that wouldn’t be fun.

Here’s a simple password generator that I’ve created. Using the System.Random Class to generate random numbers.


function Generate-Password {

  $Random = New-Object System.Random

  # Two Upper Case Characters

  [string]$Password += [char]$Random.Next(49,57)
  [string]$Password += [char]$Random.Next(65,72)

  # Two LowerCase Characters

  [string]$Password += [char]$Random.Next(97,107)
  [string]$Password += [char]$Random.Next(109,122)

  # One Special Char

  [string]$Password += [char]$Random.Next(36,43)

  # Two UpperCase Characters

  [string]$Password += [char]$Random.Next(65,72)
  [string]$Password += [char]$Random.Next(80,91)

  # One LowerCase

  [string]$Password += [char]$Random.Next(97,107)

  $Password
  $Password = $Null
}

Why not make it a a shorter script and randomize [char]49 to [char]122? Well, if I randomize any character from [char]49 to [char]122 i might get an “O” and numeric “0″, or “l”,”I” or numeric “1″. Users might find it hard to differentiate an O from an 0 so I’ve excluded Characters that look alike in the function. Also, if I use a for statement and loop through [char]$Random.Next(49,122) eight times, it’s not certain that i get an acceptable Password, i might all uppercase characters and AD wouldn’t accept that.

Now that we have a Password generator we can create our User.


PS > $Description = $Position + " (" + $Species + ")"
PS > $Title = $Rank
PS > $physicalDeliveryOfficeName = $Starship
PS > $userPrincipalName = $sAMAccountName + "@" + $Domain
PS > $mail = ([string]$Character).Replace(" ",".") + "@" + $Domain

PS > [string]$Password = Generate-Password

PS > $OU = [adsi] $Connection
PS > $User = $OU.Create("user", "cn=$cn")
PS > $User.Put("sAMAccountName", $sAMAccountName)
PS > $User.Put("userPrincipalName", $userPrincipalName)
PS > $User.Put("DisplayName", $cn)
PS > $User.Put("givenName", $givenName)
PS > $User.Put("sn", $sn)
PS > $User.Put("Description", $Description)
PS > $User.Put("l", $Starship)
PS > $User.Put("streetAddress",$Location)
PS > $User.Put("physicalDeliveryOfficeName", $physicalDeliveryOfficeName)
PS > $User.Put("Title", $Title)
PS > $User.Put("Department", $Department)
PS > $User.Put("Company", $Starship)
PS > $User.Put("mail", $mail)
PS > $User.SetInfo()

PS > $User.PsBase.Invoke("SetPassword", $Password)
PS > $User.PsBase.InvokeSet("AccountDisabled", $false)
PS > $User.SetInfo()

Now all i have to do is Collect the Generated Password in a file.


PS > $FileName = "PasswordList " + (get-date -uformat "%Y-%m-%d") + ".txt"
PS > "$sAMAccountName,$cn,$Password" | Add-Content $FileName

Running the script in our test environment would look something like this:

add-stuser01

If we repeat the script, the checker function fould tell us that the Users already exist:

add-stuser02

Now for a peek in Active-Directory snap-in dsa.msc

add-stuser03

And Finally, let’s look closer on Captain Jean-Luc Picard and see if the Values specified in the script are set.

add-stuser04

And here’s an example on the Autogenerated Password List.

Click Here to Download the Complete Script.

The Get-AD.ps1 script is also required.

Click here to download the Csv File

Rating 3.00 out of 5
[?]

4 thoughts on “Adding Users through PowerShell

  1. Wow, this is awesome … this worked great … you wouldn’t happen to have one for updating user accounts would you?

  2. This is an awesome tutorial; though difficult at first, after careful reading, I’m learning a lot. For the function called “Generate-Password”, if I simply wanted same password used for all the users could I just say

    function Generate-Password { $password = “ezAsPie” $password = $null }

    Yes this is kind of a noob question but I guess I’m looking for re-assurance :D . Thanks!

  3. Hi, If you wanted to use the same pwd for all accounts you don’t really have to use the function..
    you can simply type

    $password = “SecretPassw0rd”

    and use the $password variable when creating your useraccounts.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Comment Spam Protection by WP-SpamFree