Powershell to Create Alternate Username if one already exists

I've been trying to edit/complete a powershell script for my district which will be used to create user accounts for several thousand students. We currently have students in active directory with a firstname.lastname naming convention. The script I had used would create students using this - but when it ran into an existing account it simply would spit out the name that was a duplicate rather than doing anything about it. I would rather the script run and if an existing firstname.lastname is encountered to create a firstname.middleinitial.lastname user account. The current script also limits the samAccountName characters so they're not too long. All this information is pulled from a CSV file and used for the variables.

What is happening now is that new users are created - but if a firstname.lastname already exists - properties of new users sharing attributes of that name are input INTO the existing account which makes... odd AD user attributes. After all this - how can I get this script to search through AD and if a firstname.lastname samAccountName is encountered to leave it alone and generate a new firstname.middleinitial.lastname user account?

try {
$students = Import-Csv "$csvfile"
} catch {
 Write-Host We have a problem with the CSV file.
 exit
}

#################
# Load AD module#
#################
If (Get-Module -ListAvailable | Where-Object{$_.Name -eq "ActiveDirectory"}){
Import-Module ActiveDirectory
} else {
Write-host ActiveDirectory Module not available
exit
}

#####################
#Create the accounts#
#####################
write-host Creating Student Accounts
foreach ($student in $students){
$fname = $student."Student First Name" #Edit this to match your CSV if your header is not exactly Firstname
$lname = $student."Student Last Name" #Edit this to match your CSV if your header is not exactly Lastname
$minitial = $student."Student Middle Initial" #Edit this to match your CSV if your header is not exactly Middle Initial
$Fullname = $fname + " " + $minitial + " " + $lname
$altFullname = $fname + " " + $minitial + " " + $lname
$gradyr = $student."Grad Year" #Edit this to match your CSV if your header is not exactly Graduation Year
$bday = $student."Birthdate" #Edit this to match your CSV if your header is not exactly Birthdate
$id = $student."Student ID" #Edit this to match your CSV If your header is not Student ID
$studesc = $id + " " + $bday
$username = $fname + "." + $lname
if ($username.length -gt 20) { $username = $username.substring(0,20) } #shorten username to 20 characters for sAMAccountName
if ($studesc.length -gt 21) { $studesc = $studesc.substring(0,21) } #shorten description to not include time
$emailadd = $username + $stuemail
$principalname = $username + "@" + $domain
$altprincipalname = $altusername + "@" + $domain
$homedir = $stuhomedir1 + "\" + $username
$altusername = $fname + "." + $minitial + "." + $lname
if ($altusername.length -gt 20) { $username = $username.substring(0,20) } #shorten username to 20 characters for sAMAccountName
$altemailadd = $altusername + $stuemail
$building = $student."Grade" #Edit this to match your CSV If your header is not exactly Current Building

Write-host $Fullname $username $password

#need to check if samaccountname is already taken. If so notify admin. Have to check the shortened 20 character as well as the longer one.

Try   { $exists = Get-ADUser -LDAPFilter "(samaccountname=$username)" -Properties *
          
            
                If (!$exists)
                {
                    $createNew = $true
                }
                  
                ElseIf ($exists -and ($exists.description.trim() -eq $id))
                {
                    $createNew = $false
                    $updateUser = Get-ADUser -LDAPFilter "(sAMAccountName=$username)" -Properties *
                    #Set-ADUser -Identity $updateUser -CannotChangePassword $true
                }
               
                ElseIf (($exists) -And ($exists.description.trim() -ne $id))
               
                {
                  
                    $dupeExists = Get-ADUser -LDAPFilter "(samaccountname=$altusername)"
                    
                    if (!$dupeExists)
                    {
                        $createNew = $true
                        $username =  $altusername
                        $emailadd =  $altemailadd
                        #$principalname = $altprincipalname
                    }
                }
          }
         
    Catch { }
    If($createNew)
    {
      #$i++
      # Set all variables according to the table names in the Excel
      # sheet / import CSV. The names can differ in every project, but
      # if the names change, make sure to change it below as well.  2001-06-16
     
      
      $setpass = ConvertTo-SecureString -AsPlainText $password -force
     
      New-ADUser `
-sAMAccountName $username `
-givenName $fname `
-Surname $lname `
-Initials $minitial `
-UserPrincipalName $principalname `
-DisplayName $fullname `
-name $fullname `
-homeDrive "m:" `
-homeDirectory $homedir `
-scriptPath "logon.bat" `
-EmailAddress $emailadd `
-Description $studesc `
-ChangePasswordAtLogon $true `
-AccountPassword (ConvertTo-SecureString "$password" -AsPlainText -force) `
-Enabled $true `
-Path "ou=$gradyr,$stuou" `

start-sleep -Milliseconds 15
continue
}
}

July 4th, 2015 12:07am

Hi Mora,

I did some changes on your script assuming you will populate the CSV properly and the password field

use below script and it will do the job

$students = Import-Csv "$csvfile"
If (Get-Module -ListAvailable | Where-Object{$_.Name -eq "ActiveDirectory"}){
Import-Module ActiveDirectory
} else {
Write-host ActiveDirectory Module not available
exit
}

foreach ($student in $students){
$fname = $student."Student First Name" #Edit this to match your CSV if your header is not exactly Firstname
$lname = $student."Student Last Name" #Edit this to match your CSV if your header is not exactly Lastname
$minitial = $student."Student Middle Initial" #Edit this to match your CSV if your header is not exactly Middle Initial
$Fullname = $fname + " " + $minitial + " " + $lname
$altFullname = $fname + " " + $minitial + " " + $lname
$gradyr = $student."Grad Year" #Edit this to match your CSV if your header is not exactly Graduation Year
$bday = $student."Birthdate" #Edit this to match your CSV if your header is not exactly Birthdate
$id = $student."Student ID" #Edit this to match your CSV If your header is not Student ID
$studesc = $id + " " + $bday
$username = $fname + "." + $lname
if ($username.length -gt 20) { $username = $username.substring(0,20) } #shorten username to 20 characters for sAMAccountName
if ($studesc.length -gt 21) { $studesc = $studesc.substring(0,21) } #shorten description to not include time
$emailadd = $username + $stuemail
$principalname = $username + "@" + $domain
$homedir = $stuhomedir1 + "\" + $username
$altusername = $fname + "." + $minitial + "." + $lname
$altprincipalname = $altusername + "@" + $domain
if ($altusername.length -gt 20) { $username = $username.substring(0,20) } #shorten username to 20 characters for sAMAccountName
$altemailadd = $altusername + $stuemail
$building = $student."Grade" #Edit this to match your CSV If your header is not exactly Current Building
Write-host $Fullname $username $password


$SearhName = $username
$Searcher = [ADSISearcher]"(sAMAccountName=$SearhName)"
$Results = $Searcher.FindOne()
If ($Results -eq $Null) {write-host "$username is a New User"
     New-ADUser `
-sAMAccountName $username `
-givenName $fname `
-Surname $lname `
-Initials $minitial `
-UserPrincipalName $principalname `
-DisplayName $fullname `
-name $fullname `
-homeDrive "m:" `
-homeDirectory $homedir `
-scriptPath "logon.bat" `
-EmailAddress $emailadd `
-Description $studesc `
-ChangePasswordAtLogon $true `
-AccountPassword (ConvertTo-SecureString "$password" -AsPlainText -force) `
-Enabled $true `
-Path "ou=$gradyr,$stuou" `
start-sleep -Milliseconds 5
continue
}
ELSE{write-host "$username Already Exist, we will use $altFullname instead"
     New-ADUser `
-sAMAccountName $altusernamealtusername `
-givenName $fname `
-Surname $lname `
-Initials $minitial `
-UserPrincipalName $altprincipalname `
-DisplayName $altFullname `
-name $altFullname `
-homeDrive "m:" `
-homeDirectory $homedir `
-scriptPath "logon.bat" `
-EmailAddress $altemailadd `
-Description $studesc `
-ChangePasswordAtLogon $true `
-AccountPassword (ConvertTo-SecureString "$password" -AsPlainText -force) `
-Enabled $true `
-Path "ou=$gradyr,$stuou" `
start-sleep -Milliseconds 5
continue
}

}

 

Free Windows Admin Tool Kit Click here and download it now
July 4th, 2015 8:38pm

Hi Mora,

I did some changes on your script assuming you will populate the CSV properly and the password field

use below script and it will do the job

$students = Import-Csv "$csvfile"
If (Get-Module -ListAvailable | Where-Object{$_.Name -eq "ActiveDirectory"}){
Import-Module ActiveDirectory
} else {
Write-host ActiveDirectory Module not available
exit
}

foreach ($student in $students){
$fname = $student."Student First Name" #Edit this to match your CSV if your header is not exactly Firstname
$lname = $student."Student Last Name" #Edit this to match your CSV if your header is not exactly Lastname
$minitial = $student."Student Middle Initial" #Edit this to match your CSV if your header is not exactly Middle Initial
$Fullname = $fname + " " + $minitial + " " + $lname
$altFullname = $fname + " " + $minitial + " " + $lname
$gradyr = $student."Grad Year" #Edit this to match your CSV if your header is not exactly Graduation Year
$bday = $student."Birthdate" #Edit this to match your CSV if your header is not exactly Birthdate
$id = $student."Student ID" #Edit this to match your CSV If your header is not Student ID
$studesc = $id + " " + $bday
$username = $fname + "." + $lname
if ($username.length -gt 20) { $username = $username.substring(0,20) } #shorten username to 20 characters for sAMAccountName
if ($studesc.length -gt 21) { $studesc = $studesc.substring(0,21) } #shorten description to not include time
$emailadd = $username + $stuemail
$principalname = $username + "@" + $domain
$homedir = $stuhomedir1 + "\" + $username
$altusername = $fname + "." + $minitial + "." + $lname
$altprincipalname = $altusername + "@" + $domain
if ($altusername.length -gt 20) { $username = $username.substring(0,20) } #shorten username to 20 characters for sAMAccountName
$altemailadd = $altusername + $stuemail
$building = $student."Grade" #Edit this to match your CSV If your header is not exactly Current Building
Write-host $Fullname $username $password


$SearhName = $username
$Searcher = [ADSISearcher]"(sAMAccountName=$SearhName)"
$Results = $Searcher.FindOne()
If ($Results -eq $Null) {write-host "$username is a New User"
     New-ADUser `
-sAMAccountName $username `
-givenName $fname `
-Surname $lname `
-Initials $minitial `
-UserPrincipalName $principalname `
-DisplayName $fullname `
-name $fullname `
-homeDrive "m:" `
-homeDirectory $homedir `
-scriptPath "logon.bat" `
-EmailAddress $emailadd `
-Description $studesc `
-ChangePasswordAtLogon $true `
-AccountPassword (ConvertTo-SecureString "$password" -AsPlainText -force) `
-Enabled $true `
-Path "ou=$gradyr,$stuou" `
start-sleep -Milliseconds 5
continue
}
ELSE{write-host "$username Already Exist, we will use $altFullname instead"
     New-ADUser `
-sAMAccountName $altusernamealtusername `
-givenName $fname `
-Surname $lname `
-Initials $minitial `
-UserPrincipalName $altprincipalname `
-DisplayName $altFullname `
-name $altFullname `
-homeDrive "m:" `
-homeDirectory $homedir `
-scriptPath "logon.bat" `
-EmailAddress $altemailadd `
-Description $studesc `
-ChangePasswordAtLogon $true `
-AccountPassword (ConvertTo-SecureString "$password" -AsPlainText -force) `
-Enabled $true `
-Path "ou=$gradyr,$stuou" `
start-sleep -Milliseconds 5
continue
}

}

 

  • Proposed as answer by Taheito 10 hours 51 minutes ago
  • Marked as answer by hermaeus mora 4 hours 43 minutes ago
July 5th, 2015 12:30am

Problems I found:

  1. The following variables are used, but not defined: $stuemail, $domain, $stuhomedir1, $password, and $stuou. I assume they should be defined at the beginning of the script.
  2. The variable $altusername is used before it is defined. The statements defining $altusername, and truncating it when necessary, should be moved up.
  3. If $altusername is longer than 20 characters, the variable $username is truncated, instead of $altusername.
  4. In the 2 Get-ADUser statements, using -Properties * retrieves much more information than necessary. I would use -Properties description. The sAMAccountName property is a default property, so it does not need to be listed.
  5. Seems to be a mistake to comment out the statement: $principalname = $altprincipalname.
  6. The variable $setpass is defined but not used.
  7. The variable $building is not used.
  8. If $altusername is used instead of $username, then $homedir should also reflect the alternate name.
  9. Something should probably be done in the second Catch clause, like log or alert.

My version of the script follows (not tested).

try {
    $students = Import-Csv "$csvfile"
}
catch {
    Write-Host We have a problem with the CSV file.
    exit
}

#################
# Load AD module#
#################
If (Get-Module -ListAvailable | Where-Object{$_.Name -eq "ActiveDirectory"}){
    Import-Module ActiveDirectory
}
else {
    Write-host ActiveDirectory Module not available
    exit
}

#####################
# Assign contants   #
#####################
$stuemail = "@mydomain.com"
$domain = "mydomain.com"
$stuhomedir1 = "\\myserver\myshare"
$password = "zyX123$"
$stuou = "ou=Students,dc=MyDomain,dc=com"

#####################
#Create the accounts#
#####################
write-host Creating Student Accounts
foreach ($student in $students)
{
    $fname = $student."Student First Name"
    $lname = $student."Student Last Name"
    $minitial = $student."Student Middle Initial"
    $Fullname = $fname + " " + $minitial + " " + $lname
    $altFullname = $fname + " " + $minitial + " " + $lname
    $gradyr = $student."Grad Year"
    $bday = $student."Birthdate"
    $id = $student."Student ID"
    $studesc = $id + " " + $bday
    $username = $fname + "." + $lname
    if ($username.length -gt 20) { $username = $username.substring(0,20) }
    if ($studesc.length -gt 21) { $studesc = $studesc.substring(0,21) }
    $emailadd = $username + $stuemail
    $principalname = $username + "@" + $domain
    $altusername = $fname + "." + $minitial + "." + $lname
    if ($altusername.length -gt 20) { $altusername = $altusername.substring(0,20) }
    $altprincipalname = $altusername + "@" + $domain
    $homedir = $stuhomedir1 + "\" + $username
    $altemailadd = $altusername + $stuemail
    $building = $student."Grade"

    Write-host $Fullname $username $password

    #need to check if samaccountname is already taken. If so notify admin. Have to check the shortened 20 character as well as the longer one.

    Try
    {
        $exists = Get-ADUser -LDAPFilter "(samaccountname=$username)" -Properties Description
        If (!$exists)
        {
            $createNew = $true
        }

        ElseIf ($exists -and ($exists.description.trim() -eq $id))
        {
            $createNew = $false
            $updateUser = Get-ADUser -LDAPFilter "(sAMAccountName=$username)"
            #Set-ADUser -Identity $updateUser -CannotChangePassword $true
        }

        ElseIf (($exists) -And ($exists.description.trim() -ne $id))
        {
            $dupeExists = Get-ADUser -LDAPFilter "(samaccountname=$altusername)"
            if (!$dupeExists)
            {
                $createNew = $true
                $username =  $altusername
                $emailadd =  $altemailadd
                $principalname = $altprincipalname
                $homedir = $stuhomedir1 + "\" + $altusername
            }
        }
    }

    Catch { }
    If($createNew)
    {
        #$i++
        # Set all variables according to the table names in the Excel
        # sheet / import CSV. The names can differ in every project, but
        # if the names change, make sure to change it below as well.  2001-06-16

        New-ADUser `
            -sAMAccountName $username `
            -givenName $fname `
            -Surname $lname `
            -Initials $minitial `
            -UserPrincipalName $principalname `
            -DisplayName $fullname `
            -name $fullname `
            -homeDrive "m:" `
            -homeDirectory $homedir `
            -scriptPath "logon.bat" `
            -EmailAddress $emailadd `
            -Description $studesc `
            -ChangePasswordAtLogon $true `
            -AccountPassword (ConvertTo-SecureString "$password" -AsPlainText -force) `
            -Enabled $true `
            -Path "ou=$gradyr,$stuou" `

        start-sleep -Milliseconds 15
        continue
    }
}

Free Windows Admin Tool Kit Click here and download it now
July 5th, 2015 6:46pm

Taheito,

First of all I would like to thank you for your prompt reply! The solution you provided worked perfectly! The only thing I had not anticipated was this:

While I am testing this script on a test domain - the domain it is GOING to be used on already has users with firstname.lastname as the usernames. Their information in AD however has been there for years and is not filled in as it should be from past imports. Let me provide a fictitious example:

User Joe C Smith exists in AD. His middle initial is not populated in his properties, and his username is joe.smith.

The CSV file being pulled has account information for every user (including Joe C Smith) as well as a lot of other Joe's - Joe F Smith, Joe T Smith, etc. What winds up happening is that the "Joe.Smith" that already exists (who actually has the middle C initial - just not specified in AD) another account for "joe.c.smith" gets created. All this really means is that I have to go back and delete that user - but for ones that I don't KNOW are like this it will be a not so fun process. Now - each of these Joe's will be in a different OU and group (grade year and graduating year). Would it be possible to specify something like if joe.smith exists in an OU ($stuou) - DON'T create another account for a Joe in that OU? This may make the script far more complex than I had intended - but for long term operations I feel it may be necessary.

July 5th, 2015 9:55pm

Richard,

Thank you for your reply and assistance! I'll test out the snippet you provided and let you know what happens. I am incredibly new to this and scripts of this magnitude are fairly daunting to me right now.

  1. You are right, those variables were some of the first defined much further up in the script.
  2. That's odd - I thought I had specified it before but I'll double check that! 
  3. I'm glad you spotted that - that was a big oversight.
  4. Good to know - I'm fairly new to this and figured I'd start big and then focus things down. Thanks for the tip!
  5. This was when I was trying to test where the script was failing and was getting mixed results.
  6. This is another one of the variables that was specified before the start of this snippet. Whoops!
  7. It's used but further down the rest of the script for grouping purposes.
  8. Duly noted!
  9. There is a log creation towards the end of the script that I'm working on. ;)

I mentioned to Taheito the following (which came up AFTER what he proposed started working in the script:

While I am testing this script on a test domain - the domain it is GOING to be used on already has users with firstname.lastname as the usernames. Their information in AD however has been there for years and is not filled in as it should be from past imports. Let me provide a fictitious example:

User Joe C Smith exists in AD. His middle initial is not populated in his properties, and his username is joe.smith.

The CSV file being pulled has account information for every user (including Joe C Smith) as well as a lot of other Joe's - Joe F Smith, Joe T Smith, etc. What winds up happening is that the "Joe.Smith" that already exists (who actually has the middle C initial - just not specified in AD) another account for "joe.c.smith" gets created. All this really means is that I have to go back and delete that user - but for ones that I don't KNOW are like this it will be a not so fun process. Now - each of these Joe's will be in a different OU and group (grade year and graduating year). Would it be possible to specify something like if joe.smith exists in an OU ($stuou) - DON'T create another account for a Joe in that OU? This may make the script far more complex than I had intended - but for long term operations I feel it may be necessary.

Free Windows Admin Tool Kit Click here and download it now
July 5th, 2015 10:08pm

Actually - I just realized after more testing the easiest way to find who was there first will be that existing users do not have descriptions (as well as middle initials) in their AD accounts.
July 5th, 2015 10:17pm

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics