Hi there, getting ready to import 250 users into a new windows domain. Last IT guy thought Domains were a bad idea…

Ive researched a bit and put together a csv and a ps1 file.

Does it look good? Im a novice at powershell.

{
	#Read user data from each field in each row and assign the data to a variable as below
		
	$Username 	= $User.username
	$Password 	= $User.password
	$Firstname 	= $User.firstname
	$Lastname 	= $User.lastname
	$OU 		= $User.ou #This field refers to the OU the user account is to be created in
$email		= $User.mail
$department 	= $User.department
$title		= $User.title
$phone		= $User.telephoneNumber

	#Check to see if the user already exists in AD
	if (Get-ADUser -F {SamAccountName -eq $Username})
	{
		 #If user does exist, give a warning
		 Write-Warning "A user account with username $Username already exist in Active Directory."
	}
	else
	{
		#User does not exist then proceed to create the new user account
		
        #Account will be created in the OU provided by the $OU variable read from the CSV file
		New-ADUser `
            -SamAccountName $Username `
            -UserPrincipalName "$Username@emeneye.ac.uk" `
            -Name "$Firstname $Lastname" `
            -GivenName $Firstname `
            -Surname $Lastname `
            -Enabled $True `
            -DisplayName "$Lastname, $Firstname" `
            -Path $OU `
            -AccountPassword (convertto-securestring $Password -AsPlainText -Force) 
	}
}

3 Spice ups

Send me a PM tomorrow and I’ll take a look when I have fresh eyes!

This is all what you need

https://community.spiceworks.com/scripts/show/3682-bulk-create-active-directory-users-powershell-with-logs-less-rows-in-csv

I’m curious as to the reasoning behind your predecessor’s belief that “domains are a bad idea”. Care to elaborate on that, if you can?

Seems reasonable from a brief skim.

You should create a new OU and create these user accounts in it using the -Path param to New-ADUser. Then if things get badly screwed up you can just bulk delete them and re-create them.

Domains are just bad m’kayy

Thanks for the replies, I have created a few OUs, just waiting to hear back from HR as to who needs to be where.

I dont know how or why you let a network get 300+ computers big without adding a domain.

Adding one user required a PC login, a print server login, a vpn login, hosted exchange login, a linux file share login, and a papercut (printer accountability) login.

job security I guess

Well I did a test run, and it put the user in the correct OU, but she came in disabled, and password must be changed.

It also skipped email, job title and dept and phone.

Any advice to bring users in with password never expires and enabled? Also what may I have missed on attributes?

thanks

OUs are nothing to do with HR.

They are for organising AD users/groups, etc. for IT in order to apply group policies / delegation in an efficient manner.

It also skipped email, job title and dept and phone.

Where in the New-ADUser command do you reference these?

Any error messages?

Here’s a chink of Jitens code fromt he link he posted above:

     $Parameters = @{
        'SamAccountName'        = $Sam
        'UserPrincipalName'     = $UPN 
        'Name'                  = $Fullname
        'EmailAddress'          = $Email 
        'GivenName'             = $FirstName 
        'Surname'               = $Lastname  
        'AccountPassword'       = $password 
        'ChangePasswordAtLogon' = $true # Set False if you do not want user to change password at next logon.
        'Enabled'               = $true 
        'Path'                  = $OU
        'PasswordNeverExpires'  = $False # Set True if Password should expire as set on GPO.
    }

some of the comments should be illuminating :slight_smile:

The script also uses a technique called splatting.

1 Spice up

Add these lines at the bottom of your script:

-ChangePasswordAtLogon $False
-PasswordNeverExpires $true

Personally, I would never add either of these, but your security is up to you. Even service accounts should have password expirations as a best-practice.

As far as the accounts getting created disabled, run it on one user with

-Whatif

and it’ll usually tell you what’s going on. Check the $Error[0] variable as well. I’d suggest writing it with a Try/Catch block, but you did say you were a novice and I don’t want to add any more room for scripting syntax error (but you really should learn how to use them).

Had this page sitting open and didn’t see your more complete reply before adding my two cents.

As far as OUs and HR, although you’re technically correct, many organizations base their OUs on HR information such as location, department, security clearance, etc.

As far as OUs and HR, although you’re technically correct, many organizations base their OUs on HR information such as location, department, security clearance, etc.

THIS^

I am building OUs for Dept and Location so I can write GPOs. So OUs do have something to do with HR.

I will add those lines in there and try thank.

I dont think I have my attributes right for the script. Thanks for pointing out the code MBoyle

I tried the script from the link above:

WARNING: [ERROR]Can't create user [test G] : The server is unwilling to process the request
PS C:\Users\Administrator> if ( !(test-path $LogFolder)) {
>>     Write-Verbose "Folder [$($LogFolder)] does not exist, creating"
>>     new-item $LogFolder -type directory -Force
You cannot call a method on a null-valued expression.
At line:3 char:4
+    $FirstName = $User.FirstName.substring(0,1).toupper()+$User.FirstN ...
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : InvokeMethodOnNull

Hi there. Im getting this error when running the script that @JitenSh provided.

 $SAM = $user.FirstName.Substring(0,1) + $user.LastName #example John snow will be Jsnow

This is what my csv looks like (see pic). I was hoping to use the $username field to set the name instead of $user.Firstname.Substring.

What am I doing wrong? I appreciate the help

users.jpg

See the $ at the beginning of every cell in youtr header row? Those should not be there.

yes. I didnt think that was the correct syntax, but this is what I get when I run it with the “$” deleted:

1.) Ada Gz,The server is unwilling to process the request

here is the slightly modified that JitenSh provided and I changed to meet the environment:

<#**************************BULK AD User Creation By Allenage.com*****************************#
 Update: version 1.1 added splatting

Just add fisrtname, lastname in the csv and place on C:\ as users.csv 
Example:-

                            ******** ##### ********
                                   FirstName,lastName
                                   George,Bush
                                   Thomas,Edison
                                   Britney,Spears
                            ******** ##### ********

--> Here are examples of samaccountname or username comment out rest which does'nt suit your organistation and keep the required one.

    $SAM = $user.FirstName.Substring(0,1) + $user.LastName #example John snow will be Jsnow
    #$Sam=$User.FirstName+$User.LastName example john snow will be Johnsnow
    #$Sam=$User.FirstName example john snow will be John
    #$Sam=$User.firstName + "." + $User.lastName example john snow will be John.snow
    #$Sam=$user.Lastname+$user.Firstname.Substring(0,1) example john snow will be sjohn

#>
If (!(Get-module ActiveDirectory )) {
  Import-Module ActiveDirectory
  Clear-Host
  }

$Users=Import-csv c:\users.csv
$a=1;
$b=1;
$failedUsers = @()
$successUsers = @()
$VerbosePreference = "Continue"
$ErrorActionPreference='stop'
$LogFolder = "$env:userprofile\desktop\logs"

 ForEach($User in $Users)
   {
   $FirstName = $User.FirstName.substring(0,1).toupper()+$User.FirstName.substring(1).tolower()
   $LastName  = $User.LastName.substring(0,1).toupper()+$User.LastName.substring(1).tolower()

   $FullName = $User.FirstName + " " + $User.LastName

   $SAM = $user.FirstName.Substring(0,1) + $user.LastName #example John snow will be Jsnow as username
   <#
   $Sam=$User.FirstName+$User.LastName --> example john snow will be Johnsnow
   $Sam=$User.FirstName --> example john snow will be John
   $Sam= $User.firstName + "." + $User.lastName  --> example john snow will be John.snow
   $Sam=$user.Lastname+$user.Firstname.Substring(0,1))  --> example john snow will be sjohn
   #>

   $dnsroot = '@' + (Get-ADDomain).dnsroot

   $SAM=$sam.tolower()

   # To set Diffreent Passwords for each User add header Password on CSV and change 'P@ssw0rd@123' to $user.passsword
   $Password = (ConvertTo-SecureString -AsPlainText '$user.password' -Force)

   
   $UPN = $SAM + "CIS.LOCAL" # change "$dnsroot to custom domain if you want, by default it will take from DNS ROOT"

   $OU="CN=users, DC=Domain,DC=COM" # Choose an Ou where users will be created # Running cmd will show all OU's Get-ADOrganizationalUnit -Filter * | Select-Object -Property DistinguishedName| Out-GridView -PassThru| Select-Object -ExpandProperty DistinguishedName

   $email=$Sam + "$CIS.LOCAL" # change "$dnsroot to custom domain if you want, by default it will take from DNS ROOT"

Try {
    if (!(get-aduser -Filter {samaccountname -eq "$SAM"})){
     $Parameters = @{
    'SamAccountName'        = $Sam
    'UserPrincipalName'     = $UPN 
    'Name'                  = $Fullname
    'EmailAddress'          = $Email 
    'GivenName'             = $FirstName 
    'Surname'               = $Lastname  
    'AccountPassword'       = $password 
    'ChangePasswordAtLogon' = $true # Set False if you do not want user to change password at next logon.
    'Enabled'               = $true 
    'Path'                  = $OU
    'PasswordNeverExpires'  = $False # Set True if Password should expire as set on GPO.
}

New-ADUser @Parameters
     Write-Verbose "[PASS] Created $FullName "
     $successUsers += $FullName + "," +$SAM
    }
   
}
Catch {
    Write-Warning "[ERROR]Can't create user [$($FullName)] : $_"
    $failedUsers += $FullName + "," +$SAM + "," +$_
}
}
if ( !(test-path $LogFolder)) {
    Write-Verbose "Folder [$($LogFolder)] does not exist, creating"
    new-item $LogFolder -type directory -Force 
}

Write-verbose "Writing logs"
$failedUsers   |ForEach-Object {"$($b).) $($_)"; $b++} | out-file -FilePath  $LogFolder\FailedUsers.log -Force -Verbose
$successUsers | ForEach-Object {"$($a).) $($_)"; $a++} | out-file -FilePath  $LogFolder\successUsers.log -Force -Verbose

$su=(Get-Content "$LogFolder\successUsers.log").count
$fu=(Get-Content "$LogFolder\FailedUsers.log").count

Write-Host "$fu Users Creation Failed and " -NoNewline -ForegroundColor red
Write-Host "$su Users Successfully Created "  -NoNewline -ForegroundColor green
Write-Host "--> Launching LogsFolder have a Look and review." -ForegroundColor Magenta
Start-Sleep -Seconds 5
Invoke-Item $LogFolder

yes. I didnt think that was the correct syntax, but this is what I get when I run it with the “$” deleted:

1.) Ada Gz,The server is unwilling to process the request

In the $Parameters = @{ … } code block the only parameter needed to create the user is ’ samaccountname’ (or maybe ‘name’). Comment out all the rest and try a few test users. After each one you cna add 1 more property back (uncomment) and retest.

At a guess there is a missing @ in the UPN:

$UPN = $SAM + "CIS.LOCAL"

Also not sure if a space in the DN stored in $OU will cause issues.

edit: sure, not user

Commenting them out was very helpful. thank you! Its failing on OU. here is the OU I got from attribute editor:

OU=ProgramSupport,OU=CIS,DC=CIS,DC=LOCAL

Also Im not sure what you mean by this:

Also not user if a space in the DN stored in $OU will cause issues. 

Commenting them out was very helpful. thank you! Its failing on OU. here is the OU I got from attribute editor:

OU=ProgramSupport,OU=CIS,DC=CIS,DC=LOCAL

Also Im not sure what you mean by this:

Also not user if a space in the DN stored in $OU will cause issues. 

That OU path looks fine.

Stupid typo: sure, not user.

Im getting close! Going to skip the OU part for now. But Im trying to add my own SAM from the csv. Ive tried commenting out all of the sections

ForEach($User in $Users)
   {
   $FirstName = $User.FirstName.substring(0,1).toupper()+$User.FirstName.substring(1).tolower()
   $LastName  = $User.LastName.substring(0,1).toupper()+$User.LastName.substring(1).tolower()

   $FullName = $User.FirstName + " " + $User.LastName

   #$SAM = $user.FirstName.Substring(0,1) + $user.LastName #example John snow will be Jsnow as username
   <#
   #$Sam=$User.FirstName+$User.LastName --> example john snow will be Johnsnow
   #$Sam=$User.FirstName --> example john snow will be John
   #$Sam= $User.firstName + "." + $User.lastName  --> example john snow will be John.snow
   #$Sam=$user.Lastname+$user.Firstname.Substring(0,1))  --> example john snow will be sjohn
   #>

But its still defaulting to first initial last name. Some users have ada.gonzalez because there was another agonzalez. How can I have it pickup the SAM from the csv?