## Tuesday, 30 August 2011

### Creating bulk Active Directory user and group accounts in PowerShell using Server 2008 R2 cmdlets

This one is a departure from my normal SharePoint-related articles. Back in the day, I maintained a few batch and VBS scripts that created multiple Active Directory users and groups from CSV files. These had obvious uses for creating test accounts on a development environment, but I also used them from time to time on customer production environments when it came to provisioning new user accounts on mass.

One of the new features introduced in Windows Server 2008 R2 was the inclusion of 76 cmdlets delivering extensive Active Directory management capabilities using PowerShell. The challenge was to upgrade my old batch files to PowerShell versions using these new cmdlets, building in the following features:

• Create bulk user accounts from a CSV file, including specifying attributes and account options (e.g., change password at next logon)
• Create bulk group accounts from a CSV file, specifying a description and group type (e.g., global, security)
• Assign multiple users to groups as members using a CSV file
• Exception handling so that the script would check first to see if the account or group member existed before attempting to make the change
• To achieve this, I have created three PowerShell functions – one to create users, one to create groups, and a final one to read the CSV file, kick off one of the other two functions depending on the type of account to be created, and finally add users as group members. Once these functions are loaded in a PowerShell console, it only requires a single command to create either users or groups – along with an appropriate CSV file, of course.

Rather than go through each stage of these functions in this article, I have instead decided to annotate the script at various points so that you see what is happening. To get the functions ready for use, save them into a PS1 file using notepad or your favourite script editor and load it from a PowerShell console on a Windows Server 2008 R2 domain controller.

#Import the PowerShell module containing AD cmdlets
Import-Module ActiveDirectory

#Read a CSV file with the user or group details and create an account in AD for each entry
Param (
[parameter(Mandatory=$true)][string]$CSVPath,
[parameter(Mandatory=$true)][string]$Type,
[parameter(Mandatory=$true)][string]$OrgUnit
)

if (($Type -ne "Group") -and ($Type -ne "User"))
{
Throw New-Object System.ArgumentException("Type parameter must be specified as either 'User' or 'Group'.")
}

$csvData = Import-CSV$CSVPath
foreach ($line in$csvData) {

#Create a hash table of the account details
$accountTable = @{ 'givenName'=$line.FirstName
'sn'= $line.LastName 'displayName'=$line.DisplayName
'sAMAccountName'= $line.sAMAccountName 'password' =$line.Password
'description' = $line.Description 'ou' =$OrgUnit
}

if ($Type -eq "User") { #Call the function to create a user account CreateUser -AccountInfo$accountTable
}

if ($Type -eq "Group") { #Call the function to create a group account CreateGroup -AccountInfo$accountTable

#Get new group
$groupFilterString = "samAccountName -like "" +$line.sAMAccountName + """
$group = Get-ADGroup -Filter$groupFilterString

#Walk through each member column associated with this group
$memberColumnNumber = 1$memberColumn = "Member" + $memberColumnNumber #While a member column still exists, add the value to a group while ($line.$memberColumn) { #Check if user is already a member of the group$member = Get-ADGroupMember $group | where {$_.samAccountName -eq $line.$memberColumn }

if ($member -eq$null)
{
write-host "Adding" $line.$memberColumn "as a member to group" $group.Name try {$userFilterString = "samAccountName -like "" + $line.$memberColumn + """
$user = Get-ADUser -Filter$userFilterString
Add-ADGroupMember -Identity $group -Members$user
}
catch
{
write-host "There was a problem adding" $line.$memberColumn "as a member to group" $group.Name "-"$_ -ForegroundColor red
}
}
else
{
write-host "User" $line.$memberColumn "not added to group" $group.Name "as it is already a member" -ForegroundColor blue }$memberColumnNumber = $memberColumnNumber + 1$memberColumn = "Member" + $memberColumnNumber } } } } #Create an Active Directory user Function CreateUser { Param($AccountInfo)

try
{
#Check to see if the user already exists
$userFilterString = "samAccountName -like "" +$AccountInfo['sAMAccountName'] + """
$user = Get-ADUser -Filter$userFilterString

#If user not already created, create them
if ($user -eq$null)
{
write-host "Creating user account:" $AccountInfo['sAMAccountName'] #Create the user account object New-ADUser -SamAccountName$AccountInfo['sAMAccountName'] 
-Name $AccountInfo['displayName']  -DisplayName$AccountInfo['displayName'] 
-GivenName $AccountInfo['givenName']  -Surname$AccountInfo['sn'] 
-Path $AccountInfo['ou']  -ChangePasswordAtLogon$true 
-AccountPassword (ConvertTo-SecureString $AccountInfo['password'] -AsPlainText -Force)  -Description$AccountInfo['description'] 
-Enabled $false #Set 'User must change password at next logon' to true after user has been created #For some reason, the option wasn't set during New-ADUser - could be a bug?$user = Get-ADUser -Filter $userFilterString Set-ADUser$user -ChangePasswordAtLogon $true } else { write-host "User"$AccountInfo['sAMAccountName'] "not created as it already exists" -ForegroundColor blue
}
}
catch
{
write-host "There was a problem creating the user" $AccountInfo['sAMAccountName'] "-"$_ -ForegroundColor red
}
}

#Create an Active Directory group
Function CreateGroup {
Param($AccountInfo) try { #Check to see if the group already exists$groupFilterString = "samAccountName -like "" + $AccountInfo['sAMAccountName'] + """$group = Get-ADGroup -Filter $groupFilterString if ($group -eq $null) { write-host "Creating group account:"$AccountInfo['sAMAccountName']

#Create the group account object
New-ADGroup -SamAccountName $AccountInfo['sAMAccountName']  -Name$AccountInfo['sAMAccountName'] 
-Path $AccountInfo['ou']  -GroupScope Global ` -GroupCategory Security } else { write-host "Group"$AccountInfo['sAMAccountName'] "not created as it already exists" -ForegroundColor blue
}
}
catch
{
write-host "There was a problem creating the group" $AccountInfo['sAMAccountName'] "-"$_ -ForegroundColor red
}
}

## Creating users

Once the functions have been loaded in a PowerShell console, you are ready to start creating user accounts from a CSV file. The header of the CSV file for this example should be, as follows:

Something to note is that I have used a very limited number of attributes when creating a user account – for example, I haven’t specified an Office, Department, Phone Number, Address, etc. You can extend the script to include these by adding extra columns to the CSV file and adapting the CreateUser function in the script, using the appropriate parameters for the New-ADUser cmdlet, as specified on TechNet here.

Once you have these columns populated with user accounts, save the CSV file to a local or network path. For this example, I am going to copy the file into C:\Scripts and call it UserAccounts.csv.

You now need to decide which Organisational Unit (OU) to store the users in Active Directory. I could have added this information to an extra column in the CSV file and made a slight modification to the script, but I decided to use a single OU in the PowerShell command instead. You can always move them to a different OU afterwards using the Active Directory Users and Computers console, if required.

To create my users in the OU “Staff” for the domain “acme.local”, I would need to use the following command:

Create-ADAccountsFromCSV -CSVPath "C:\Scripts\UserAccounts.csv" -OrgUnit "OU=Staff,DC=acme,DC=local” -Type "User"

The script will output operation progress to the console, including a warning when it discovers that an account already exists and will not attempt to create it.

## Creating groups and assigning members

sAMAccountName,Member1,Member2,Member3,Member4,Member5

The first column should contain the group name, followed by a column for each group member. Note that although I have only included Member 1 to 5 in the example above, you can have as many members as you like by creating extra columns in the header for Member6, Member7, etc.

As with adding users. there are also extra parameters available for the New-ADGroup cmdlet, as specified on TechNet here.

Once you have the CSV file formatted with the correct groups and their members, save it to a local or network path for use with the script. For this example, I am going to copy the file into C:\Scripts and call it GroupAccounts.csv. To create my groups in the OU “Groups” for the domain “acme.local”, I would need to use the following command:

Create-ADAccountsFromCSV -CSVPath "C:\Scripts\GroupAccounts.csv" -OrgUnit "OU=Groups,DC=acme,DC=local” -Type "Group"

As with creating users, the script will output progress to the PowerShell console, including warnings when either a group already exists or a user is already a member of the group - in both cases it will ignore these operations and move on without making a change.

1. I created the ad domain accounts but the users can't login to the SharePoint site using this format domain\user. It might be a permissions thing. If anyone has any ideas I would appreciate the help.

Thanks!

2. If you used the script as is above, then the user accounts will be disabled by default. Either enable them using Active Directory Users and Computers, or re-provision with the -Enabled switch set to $true 3. Hi Phil, I've created a .ps1 file with your script, loaded it in powershell (.\CreateGroups.ps1) and it doesn't recognise Create-ADAccountsFromCSV. i.e. The term 'Create-ADAccountsFromCSV' is not recognized as the name of a cmdlet, function, script file, or operable progr am. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. Am I doing something wrong? Cheers 4. Yes :-) If the script is located in the path you are residing in currently then type . .\CreateGroups.ps1 - that is [dot][space].\CreateGroups.ps1 If you are not in the path currently, you can type . "c:\path\CreateGroups.ps1" See my article here on this: http://get-spscripts.com/2011/03/running-powershell-ps1-script-files-in.html. It applies to the standard PowerShell console as well as the SharePoint Management Shell. 5. Hi Phil, Thanks for sharing this; worked a treat. I ran into the issue of the accounts being disabled. Is there any reason you didn't include the -Enabled switch by default in the script? Is it recommended to enable them as a separate process? Cheers, Chris 6. Hi Chris, it looks as though the Enabled switch is in the script at the end of the New-ADUser command, unless there is a problem with the way I have implemented it or I have misunderstood you? Phil 7. Hi Phil, I am getting a problem creating the user - The search filter cannot be recognized using the following: Create-ADAccountsFromCSV -CSVPath "dir\to\file.csv" -OrgUnit "ou=year07,ou=students,dc=school,dc=local" -Type "User" Not sure if i'm doing anything wrong here :) 1. CSV file must contains an header that can be decoded @echo sAMAccountName,FirstName,LastName,DisplayName,Description,Password >> users.csv 8. Hi Phil, can you post a sample csv file with the header? Thanks! 9. http://raghuitadmin.blogspot.in/2012/02/create-bulk-users-in-active-directory.html 10. Hi Phil, How much time should it take to load about 1,000,000 Users? I dont know if that times that im getting are reasonable(~24hrs) Thanks, Gil 11. I appreciate what you have done and it works great for me but I do have one question. I would like to make this a single executable application (primal script) or be able to run it as a windows task daily but I am having issues. I have all my additional parameters integrated in the script (path to CSV, OU Path Account type) but I cannot get it to run without typing in "Create-ADAccountsFromCSV" I have tried passing this as a parameter in the task scheduler no luck (it loads the AD module then disappears). I though that it is just calling the first function to create the users so I added it in the script under "Import-Module ActiveDirectory" no luck I get the following error "The term 'Create-ADAccountsFromCSV' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. Is there a way I can just type in . 'C:\Scripts\AD_NewUsers.ps1 and have it execute? Thanks for any help. 12. You could try taking a look at these articles: http://get-spscripts.com/2011/01/running-sharepoint-powershell-script.html, http://get-spscripts.com/2011/03/running-powershell-ps1-script-files-in.html 13. Awesome thanks for the script and info but I do have one question. I modified it so the account are enabled when created by adding "-Enabled$true" everything seems to work accounts are created and enabled but you are unable to log into any of the accounts until you unlock them first (they don't say or show they are unlocked) I stumbled across this while trying to figure out why I could not log in with the accounts.

Is this something that the module is calling or is there something I am missing and need to add so when the accounts are created they work?

Thanks.

14. I have just tried it myself with the -Enabled $true option and it works ok, so not sure what this is, sorry 15. Question when I run the following script it error "The term 'CreateUser' is not recognized as a name of a cmdlet" but if I run it again right after in the same powershell window it works on the second time. How do I get it to work the first time Here is what I have and the modification changes I have made to the original. Import-Module ActiveDirectory #Read the CSV file$csvData = Import-CSV "C:\Scripts\Accounts\XXXX.csv"

foreach ($line in$csvData) {
#Create a hash table of the account details
$accountTable = @{ 'GivenName'=$line.givenName
'Sn'= $line.sn 'DisplayName'=$line.displayName
'SamAccountName'= $line.samAccountName 'Password' =$line.password
'Description' = $line.description 'Department' =$line.department
'Initials' = $line.initials 'Office' =$line.physicalDeliveryOfficeName
'UPN' = $line.userPrincipalName 'ou' =$line.OU
}

#Call the function to create a user account
CreateUser -AccountInfo $accountTable } #Create an Active Directory user Function CreateUser { Param($AccountInfo)

The rest is the same from this function on down.

Thanks for any input or help.

16. Phil, this is fantastic...exactly what I was looking for! I had a heck of a time getting it to install but eventually got it working. I changed -Enabled $false to$true and -ChangePasswordAtLogon $false to$true (since I need to manually configure all 37 accounts!), and breezed through creating all 37 accounts. Also created 26 groups and added (up to 11) members to all of them. Went like clockwork. Thank you so much!!

In case anybody's still using 2008R2 and getting the "'Create-ADAccountsFromCSV' is not recognized" error like I was, here's what I had to do:

Close PS
Right-click the PS icon in the taskbar, and click "Import System Modules"
type Set-ExecutionPolicy RemoteSigned in the PS window
Go to the folder containing your .ps1 file, rt-click it and run in powershell
Back in PS, run the Create-ADAccountsFromCSV commands
Viola! Users, Groups, and Group Members!!

17. Hi Bill, thanks for the comments and extra info - much appreciated

18. does it create home directories and set their permissions as well?

19. for "does it create home directories and set their permissions as well?" no it don't please read the post from the start

20. Hi Phil,

Your scripts work great for AD account. Is it possible to include the exchange mailbox creation in your scripts? Usually creating a new user and mailbox should occur at the same time.

Thanks,

21. Phil,
Thanks for the awesome script. How do I add user email address in this script?

22. I keep getting the same error with each user "There was a problem creating the user juan.palopolo - Directory object not found""

23. Kindly try ad manager tool, i am using this ,pretty well so only i suggest you guys.

24. الاول خدماتها تغطى جميع انحاء المملكة فهى افضل شركات التنظيف بجدة ومكة والرياض وينبع والاحساء والدمام نتميز باننا نوفر افضل العماله المدربة الماهرة نقدم تنظيف منازل وخزانات وبيوت وفلل وشقق ومجالس وسجاد وموكيت
شركة تنظيف خزانات بجدة
شركة تنظيف منازل بالدمام
شركة نقل اثاث بينبع
شركة تنظيف خزانات بينبع

شركة تنظيف بمكة
شركة تنظيف بالقطيف
شركة تنظيف بالاحساء
شركة شراء اثاث مستعمل بالرياض
شركة نقل اثاث بجدة
شركة تنظيف كنب بشرق الرياض
مكافحة الصراصير
تنتشر في السعودية عدة انواع من الصراصير كالصراصير الامريكية والالمانية والشرقية وتعد خطيره لانها تنقل الميكروبات وتسبب الامراض للانسان من هنا جاءت اهمية مكافحتها والتخلص منها نستخدم افضل مبيدات مكافحة الصراصير المثبت فعاليتها وتغطى خدماتنا كافة مناطق المملكة فالاول تشتهر بانها احسن شركة مكافحة صراصير بالرياض واحسن شركة مكافحة صراصير بمكة واحسن شركة مكافحة صراصير بجدة واحسن شركة مكافحة صراصير بالمدينة المنورة

شركة مكافحة صراصير بالجبيل