OK guys, i've edited my script for user creation and now it's almost perfect except one thing that i cant figure out
how to make the hash table read the Variable for the "$GivenName $Surname"
and make the Name of the user, because now it's creating users without the Name parameter
or I need to creat a header for $GivenName and $surname in the csv file
cls
#get the csv file
$filepath = import-csv "C:\users.csv"
#set the variable for the uers
$newusers = $filepath
#set Passwords for new users
$securepassword = ConvertTo-SecureString "BlahBlah" -AsPlainText -Force
foreach ($user in $newusers) {
#get user information
$User_Creation_Settings = #{
Name = "$GivenName $Surnam"
GivenName = $user.GivenName
Surname = $user.Surnam
UserPrincipalName = $user.UserPrincipalName
SamAccountName = $user.SamAccountName
Path = $user.Path
ScriptPath = $user.ScriptPath
ChangePasswordAtLogon = $false
Department = $user.Department
DisplayName = $user.DisplayName
Description = $user.Description
Title = $user.'Job Title'
AccountPassword = $securepassword
Enabled = $true
}
New-ADUser #User_Creation_Settings
#Get Groups information
$group1 = $user.Group1
$group2 = $user.Group2
$group3 = $user.Group3
$group4 = $user.Group4
#Add the users in to Groups
Add-ADPrincipalGroupMembership -Identity $user.SamAccountName -MemberOf $user.group1
Add-ADPrincipalGroupMembership -Identity $user.SamAccountName -MemberOf $user.group2
Add-ADPrincipalGroupMembership -Identity $user.SamAccountName -MemberOf $user.group3
Add-ADPrincipalGroupMembership -Identity $user.SamAccountName -MemberOf $user.group4
Write-Host "`n"
Write-Host "The account for $GivenName $Surnam created in $OuPath successfully "
}
pause
so i've figured it out and i'm posting the solution
for the solution of the issue that i've described, i had to make Powershell think that "First name" and "Last Name" are one whole variable which is split in the middle, that's why i've used the parentheses with a "$" sign before them, Power Shell will think that you are using the $user from the loop, and will "Popup" the headers from the CSV file.
here is the whole script
cls
#get the csv file
$filepath = import-csv "C:\users.csv"
#set the variable for the uers
$newusers = $filepath
#set Passwords for new users
$securepassword = "BlahBlah"
foreach ($user in $newusers) {
#get user information
$User_Creation_Settings = #{
Name = "$($user.'First Name') $($user.Lastname)"
GivenName = $user.'First Name'
Surname = $user.Lastname
UserPrincipalName = $user.UserPrincipalName
SamAccountName = $user.SamAccountName
Path = $user.Path
ScriptPath = $user.ScriptPath
ChangePasswordAtLogon = $false
Department = $user.Department
DisplayName = $user.DisplayName
Description = $user.Description
Title = $user.'Job Title'
AccountPassword = ConvertTo-SecureString $securepassword -AsPlainText -Force
Enabled = $true
}
New-ADUser #User_Creation_Settings
#Get Groups information
$group1 = $user.Group1
$group2 = $user.Group2
$group3 = $user.Group3
$group4 = $user.Group4
#Add the users in to Groups
Add-ADPrincipalGroupMembership -Identity $user.SamAccountName -MemberOf $user.group1
Add-ADPrincipalGroupMembership -Identity $user.SamAccountName -MemberOf $user.group2
add-ADPrincipalGroupMembership -Identity $user.SamAccountName -MemberOf $user.group3
Add-ADPrincipalGroupMembership -Identity $user.SamAccountName -MemberOf $user.group4
Write-Host "`n"
Write-Host "The account for $($user.'First Name') $($user.Lastname) created in $($user.Path) successfully "
}
pause
So in that case:"$($user.'First Name') $($user.Lastname)"
powershell will behave like you entered one whole variable.
The short answer is that both are fine, because both are valid ways of creating hashtables in PowerShell. For more information, check out about_Splatting.
Personally, I use single quotes around strings across the board and leave variables alone so that PowerShell doesn't think I'm trying to call a function. As mentioned, this is not required here and frankly can make your code look messier than it needs to be.
A few things to watch out for:
Name = $firstname $lastname # invalid because of the space
'class' = win32_logicaldisk # invalid: PowerShell will look for the function win32_logicaldisk
GivenName = '$firstname' # because single quotes are used, PowerShell will not replace the variable; GivenName will literally be $firstname
Both the above splatting are fine and the reason for the color change is in the first Hashtable "$firstname $lastname" is a string as you have mentioned it in quotes, Editor represents Strings in Brown color and variables in black color.
In the second Hashtable you used single quotes for all the Keys and values and again those are understood and represented as Strings by the editor.
No harm either way.
Related
I am very new to powershell, still trying to figure out how it works. I have so far written a short script to take details from a CSV and poulate properties in AD.
If I use the username i.e smithj it works fine but I can't get it to take a name like John Smith and find the account it is associated with. This is the same with the manager field, it will take the username but I cant get it to take a full name.
Any help or advice would be much appreciated.
Import-module ActiveDirectory
$List = Import-CSV "\\SharedServer\shared\MYCSV.csv" | % {
$User = $_.UserName
$ID = $_.EmployeeID
$EmployeeNumber = $_.EmployeeNumber
$Description = $_.Description
$Department = $_.Department
$Title = $_.Title
$AccountExpirationDate = $_.AccountExpire
$Manager = $_.Manager
Set-ADUser $User -employeeID $ID -EmployeeNumber $EmployeeNumber -Description $Description -Department $Department -Title $Title -Manager $Manager -AccountExpirationDate $AccountExpirationDate
}
Depending on what the CSV contains for UserName and Manager, the best would be to have the SamAccountName or DistinguishedName because these attributes are unique within the same domain.
UserPrincipalName or EmailAddress would also do nicely for targeting the correct user.
From your question however, I gather that the CSV has the users Name in there that should correspond to the Name property of an AD user.
In that case I agree with I.T Delinquent that you can use that in the Filter parameter for Get-ADUser and that is also what my example code below uses.
Then there is the question of how you have entered the date for the AccountExpirationDate in the CSV file..
This parameter wants a DateTime object, not a string, so you'll have to convert that before use.
Finally, I would suggest using Splatting for cmdlets like Set-ADUser that take a lot of parameters.
Something like this:
Import-CSV "\\SharedServer\shared\MYCSV.csv" | ForEach-Object {
$user = Get-ADUser -Filter "Name -eq '$($_.UserName)'" -ErrorAction SilentlyContinue
if (!$user) {
Write-Warning "User '$($_.UserName)' not found"
}
else {
# convert the date string from the CSV into a real DateTime object
# Since I cannot see the CSV, you may need to do this using [DateTime]::ParseExact()
$expireDate = Get-Date $_.AccountExpire
# create a Hashtable for the parameters
$userProps = #{
'EmployeeID' = $_.EmployeeID
'EmployeeNumber' = $_.EmployeeNumber
'Description' = $_.Description
'Department' = $_.Department
'Title' = $_.Title
'AccountExpirationDate' = $expireDate
}
# get the manager object from the name
$manager = Get-ADUser -Filter "Name -eq '$($_.Manager)'" -ErrorAction SilentlyContinue
if ($manager) {
$userProps['Manager'] = $manager.DistinguishedName
}
$user | Set-ADUser #userProps
}
}
When using UserPrincipalName or EmailAddress, change the Filter into "UserPrincipalName -eq '$($_.UserName)'" or "EmailAddress -eq '$($_.UserName)'".
You might even want to experiment with Ambiguous Name Resolution..
I would use Get-ADUser and then pipe the object that was returned into Set-ADUser. Here is a quick example:
Get-ADUser -Filter " Name -eq 'Name here' " | Set-ADUser -employeeID $ID
I have been given the task of creating a school's worth of users (UK Secondary). The PS to create the users from a CSV, what I need to do is add the newly created users to various groups at the same time.
The code I am using is as follows
$DCName = '<DC FQDN>'
Import-Csv -Path "D:\Import.csv" |
ForEach-Object {
$Displayname = $_.'FirstName' + " " + $_.'LastName'
$UPN = $_.'UPN'
$GroupName = $_.'GroupName'
$Prop = #{
Name = $Displayname
DisplayName = $_.'FirstName' + " " + $_.'LastName'
GivenName = $_.'FirstName'
Surname = $_.'LastName'
UserPrincipalName = $UPN
EmailAddress = $UPN
SamAccountName = $_.'SAM'
AccountPassword = (ConvertTo-SecureString $_.'Password' -AsPlainText -Force)
Enabled = $true
Path = $_.'OU'
ChangePasswordAtLogon = $false
Title = $_.'JobTitle'
StreetAddress = $_.'Street'
City = $_.'Town'
State = $_.'County'
PostalCode = $_.'PostCode'
OfficePhone = $_.'Telephone'
Company = $_.'Company'
Department = $_.'Department'
HomeDrive = $_.'HomeDrive'
HomeDirectory = $_.'Home-Directory'
OtherAttributes = #{
'extensionAttribute1'= $_.'ExtendedAttribute1';
'extensionAttribute2'= $_.'ExtendedAttribute2';
'extensionAttribute14'= $_.'ExtendedAttribute14';
'extensionAttribute15'= $_.'ExtendedAttribute15';
'proxyAddresses' = "SMTP:" + $UPN;}
Server = $DCName
}
New-ADUser #prop
Add-ADGroupMember -Identity $GroupName -Members $_.'SAM'
}
The user gets created with all properties correctly set. It fails with the following error
Add-ADGroupMember : Cannot find an object with identity: 'Test.User' under: 'DC=AD,DC=example,DC=uk'.
At C:\Scripts\NewUserFromCSV2.ps1:47 char:10
+ Add-ADGroupMember -Identity $GroupName -Members $_.'SAM'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Test.USer:ADPrincipal) [Add-ADGroupMember], ADIdentityNotFoundException
+ FullyQualifiedErrorId : SetADGroupMember.ValidateMembersParameter,Microsoft.ActiveDirectory.Management.Commands.AddADGroupMember
It looks like the Add-ADGroupMember command can't find the user that has just been created, however, if that is the case I don't understand why.
Also at the moment, my CSV has only one group in the 'GroupName', what would be the best way to add the user to multiple groups? e.g. School-All-Staff, Teaching-Staff, Science-Teachers etc.
Thanks in advance for any help received.
As it's a bulk operation, I would just split the user creation from the group membership.
Create all the users first, then add them to the groups:
$DCName = '<DC FQDN>'
$Users = Import-Csv -Path "D:\Import.csv"
$Users | ForEach-Object {
$Displayname = $_.'FirstName' + " " + $_.'LastName'
$UPN = $_.'UPN'
$Prop = #{
## properties as per original code ##
}
New-ADUser #prop
}
$Users | ForEach-Object {
$GroupName = $_.'GroupName'
Add-ADGroupMember -Identity $GroupName -Members $_.'SAM'
}
The to add the users to multiple groups:
If you've got a semicolon separated list of the groups in GroupName eg
School-All-Staff;Teaching-Staff;Science-Teachers
Split will convert this to an array then you can loop through them:
$_.'GroupName' -split ';' | ForEach-Object {
Add-ADGroupMember $_ –Member $user.'SAM'
}
(edit: updated to semicolon as you have a csv source)
I got it working as a combined script in the end and added in error checking for pre-existing users, existing staff often move to the new school that is being added to the Trust prior to its addition to our AD and get included in the list of users to create.
Also added log file creation to record newly created users and list those whose SAMAccount name already exists so we can check to see if the user does need creating or if they need moving from another School OU.
This is my final code:
#Get deafult variables to tidy up created variables at the end
$ExistingVariables = Get-Variable | Select-Object -ExpandProperty Name
#New User Code Starts Here>
#Variables not set by CSV
#Set DC name to update - prevents errors due to replication delay
$DCName = '<DC FQDN>'
#Create log files
"Users Exist in AD" | Out-File -FilePath "D:\Logs\ExistingUsers-$(get-date -f yyyyMMdd).txt" -Append
"New Users Created" | Out-File -FilePath "D:\Logs\NewUsers-$(get-date -f yyyyMMdd).txt" -Append
#Specify path and file to import
Import-Csv -Path "D:\Import.csv" |
#Iterate through each row in the CSV
ForEach-Object {
#Set per object variables from fields in the CSV
$DisplayName = $_.'FirstName' + " " + $_.'LastName'
$UPN = $_.'UPN'
$GroupName1 = $_.'GroupName1'
$GroupName2 = $_.'GroupName2'
$GroupName3 = $_.'GroupName3'
$GroupName4 = $_.'GroupName4'
$SAM = $_.'SAM'
$Password = $_.'Password'
$SAMTest = Get-ADUser -Filter {(sAMAccountName -eq $SAM)} -Server $DCName
#Splatting Hash Table holds all user attribute properties set in the CSV
$Prop = #{
Name = $DisplayName
DisplayName = $DisplayName
GivenName = $_.'FirstName'
Surname = $_.'LastName'
UserPrincipalName = $UPN
EmailAddress = $UPN
SamAccountName = $_.'SAM'
AccountPassword = (ConvertTo-SecureString $_.'Password' -AsPlainText -Force)
Enabled = $true
Path = $_.'OU'
ChangePasswordAtLogon = $false
Title = $_.'JobTitle'
StreetAddress = $_.'Street'
City = $_.'Town'
State = $_.'County'
PostalCode = $_.'PostCode'
OfficePhone = $_.'Telephone'
Company = $_.'Company'
Department = $_.'Department'
OtherAttributes = #{
'extensionAttribute1'= $_.'ExtendedAttribute1';
'extensionAttribute2'= $_.'ExtendedAttribute2';
'extensionAttribute14'= $_.'ExtendedAttribute14';
'extensionAttribute15'= $_.'ExtendedAttribute15';
'proxyAddresses' = "SMTP:" + $UPN;}
Server = $DCName
}
#Check if SAMAccount name exists in AD and skip existing users
if ($SAMTest -ne $Null)
{
#Get UPN property of the pre-existing user
$Exist = Get-ADUser -Filter {(sAMAccountName -eq $SAM)} -Properties 'userprincipalname'
#write UPN value to variable
$ExistUPN = $Exist.userprincipalname
#Update log of pre-existing users
"$DisplayName exists with email $ExistUPN" | Out-File -FilePath "D:\Logs\ExistingUsers-$(get-date -f yyyyMMdd).txt" -Append
#Write to screen
Write-Host "$DisplayName already exists in AD" -ForegroundColor Red
}
else
{
#Create new user with the attribute properties collected above
New-ADUser #prop
#Check if group fields in CSV were populated, if true add user to group, if false skip
if ($_.'GroupName1'){Add-ADGroupMember -Identity $_.'GroupName1' -Members $_.'SAM' -Server $DCName}
if ($_.'GroupName2'){Add-ADGroupMember -Identity $_.'GroupName2' -Members $_.'SAM' -Server $DCName}
if ($_.'GroupName3'){Add-ADGroupMember -Identity $_.'GroupName3' -Members $_.'SAM' -Server $DCName}
if ($_.'GroupName4'){Add-ADGroupMember -Identity $_.'GroupName4' -Members $_.'SAM' -Server $DCName}
#Update New user log
"$UPN" | Out-File -FilePath "D:\Logs\NewUsers-$(get-date -f yyyyMMdd).txt" -Append
#Write to screen
Write-Host "User $SAM created at $((Get-Date).ToString('hh:mm'))" -ForegroundColor Green
}
}
#End Of New User Code
#Remove variables set by script - keeps PS memory space tidy
$NewVariables = Get-Variable | Select-Object -ExpandProperty Name | Where-Object {$ExistingVariables -notcontains $_ -and $_ -ne "ExistingVariables"}
if ($NewVariables)
{
Write-Host "Removing the following variables:`n`n$NewVariables"
Remove-Variable $NewVariables
}
else
{
Write-Host "No new variables to remove!"
}
I used the bit about clearing up variables because the values seemed to persist if the PowerShell session remained open and it was causing odd things to happen. I also removed the home drive attributes because the file server specified hasn't been implemented yet but management still wants the users in AD now.
For reference my import.csv looks like this
FirstName,LastName,UPN,SAM,Password,OU,JobTitle,Street,Town,County,PostCode,Telephone,Company,Department,ExtendedAttribute1,ExtendedAttribute2,ExtendedAttribute14,ExtendedAttribute15,GroupName1,GroupName2,GroupName3,GroupName4
Test,User,Test.Users#domain.uk,Test.User,,"OU=Admin Staff,OU=User Resources,OU=School,OU=Trust Schools,DC=AD,DC=Trust,DC=org",,Street Name,TownName,County,AA11 1AA,116123,Name Of School,Name Of Trust,,Staff,,,AllStaffGroup,AdminStaffGroup,SpecialPermissionsGroup,Group4
My need is to feed attribute 'Ms-Ds-ConsistencyGUID' in our AD but It looks way more difficult than I expected. Here is the script I have done so far :
ipmo activedirectory
# Combo box
$collection = #()
$a = [System.Management.Automation.Host.ChoiceDescription]::new("&Oui")
$collection+=$a
$b = [System.Management.Automation.Host.ChoiceDescription]::new("&Non")
$collection+=$b
$annuler =
[System.Management.Automation.Host.ChoiceDescription]::new("&Annuler")
$collection+=$annuler
$prompt = $Host.UI.PromptForChoice("Messagerie","L'utilisateur aura-t-il
besoin d'une messagerie ?",$collection,0)
Switch ($prompt) {
0 {
# Import CSV file
$users = import-csv C:\Users\...\Desktop\test_bulk.csv -delimiter ";"
foreach ($User in $users)
{
# User's info
$Displayname = $User.Givenname + " " + $User.Surname
$Usersurname = $User.Surname
$Userfirstname = $User.Givenname
$SAM = $User.Samaccountname
$OU = $User.path
$password = $User.Password
$UPN = $SAM + "#...com"
$emailaddress = ($User.Givenname + "." + $User.Surname + "#...com").ToLower()
$description = get-aduser -Identity $User.gpuser -Properties Description | select -ExpandProperty description
$homedirectory = "\\server\$($User.Samaccountname)"
$infotab = $User.invcode
[guid]$obGUID = get-aduser $newuser -Properties objectguid | Select -ExpandProperty Objectguid
$newuser = New-ADUser -PassThru -Name $Displayname -Surname
$Usersurname -GivenName $Userfirstname -SamAccountName $SAM -Path $OU
-AccountPassword (ConvertTo-SecureString $password -AsPlainText -Force) -
Enabled $true -ChangePasswordAtLogon $false -PasswordNeverExpires $false
-UserPrincipalName $UPN -EmailAddress $emailaddress -Description
$description -ScriptPath "login.vbs" -HomeDrive "H:" -HomeDirectory
$homedirectory
-OtherAttributes #{businesscategory="Internal";
info="|MAIL_MAILBOX_O365||RU_$($infotab)|"; ms-ds-consistencyguid =
"$obguid"}
# Group membership
$gpuser = Get-ADPrincipalGroupMembership $User.gpuser | select -ExpandProperty name
$excludefromlist = #("Group1", "Group2", "Group3")
$newgrouplist = $gpuser | where {$_ -notin $excludefromlist}
# Creation of the new user
Add-ADPrincipalGroupMembership -Identity $newuser -MemberOf $newgrouplist
}
}
1 { ... }
2 { ... }
}
As you can see attribute 'ms-ds-consistencyGUID' is fed with the variable '$obguid'. But that variable extracts objectGUID out of the new user's profile which is on the way to be created. This is kinda tricky.
Do you have any idea how I can set that?
You can't set the attribute at the time of creation since the GUID is not known yet. You will have to update it after you create it.
You're already specifying the PassThru parameter, which means that the New-ADUser command will return the new user, which then means you can pass that to Set-ADUser.
$newuser = New-ADUser -PassThru ...
Set-ADUser $newuser -Replace #{"ms-ds-consistencyGUID" = $newuser.ObjectGUID}
#Gabriel, You mean I can state these two cmdlets without any issue :
Add-ADPrincipalGroupMembership -Identity $newuser -MemberOf $newgrouplist
Set-ADUser $newuser -Replace #{"ms-ds-consistencyGUID" = $newuser.ObjectGUID}
I thought it was not the right way to go but it finally works so...
I am creating a script that will help my colleagues to create a new AD user. This is what I have done so far:
ipmo activedirectory
$users = import-csv C:\Users\...\Desktop\test_bulk.csv -delimiter ";"
foreach ($User in $users)
{
$Displayname = $User.Givenname + " " + $User.Surname
$Usersurname = $User.Surname
$Userfirstname = $User.Givenname
$SAM = $User.Samaccountname
$OU = $User.path
$password = $User.Password
$newuser = New-ADUser -PassThru -Name $Displayname -SamAccountName $SAM -
GivenName $Userfirstname -Surname $Usersurname -AccountPassword (ConvertTo-SecureString $password -AsPlainText -Force)-Enabled $true -Path $OU -ChangePasswordAtLogon $false -PasswordNeverExpires $true -OtherAttributes #{businesscategory="Internal"}
$gpuser = Get-ADPrincipalGroupMembership $User.gpuser | select -ExpandProperty name
Add-ADPrincipalGroupMembership -Identity $newuser -MemberOf $gpuser
}
As you can see I have set a variable $gpuser so I can output a user's group membership to set all these into the new user's membership.
But there is a little hurdle... I need to remove up to three groups from the retrieved list.
I mean each time I output a user's membership I need to remove a few groups IF they are present in the list.
The thing is I don't know how to script that and where to start.
You should take a look at the Where-Object cmdlet and the -notin operator.
Basically you will do something like this:
$excludeFromThisList = #("group1", "group2")
$newGroupList = $gpuser | Where-Object { $_ -notin $excludeFromThisList }
I'm trying to get a specific AD User and change their UPN, but not their UPN suffix.
As you can see at the moment I have to manually enter their current UPN suffix which is a bit pointless since you have to go into AD to find that anyway, is there some string like $_.UPNSuffix that will call the user's current Suffix?
$container = "OU=MyOU,DC=MyDomain,DC=local"
$Filter = Read-Host -Prompt "Enter users Username/P-number"
$UPNSuffix = Read-Host -Prompt "Enter users current UPN Suffix"
$users = Get-ADUser -Filter "UserPrincipalName -like '$Filter*'" -SearchBase $container
Foreach ($user in $users)
{
$newFQDN = $user.GivenName + "." + $user.Surname
$NewDN = $user.GivenName + " " + $user.Surname
Set-ADUser -Identity $user -UserPrincipalName $newFQDN#$UPNSuffix -SamAccountName $newFQDN
Write-Host "User's UPN is now $newFQDN#$UPNSuffix"
}
You can get the UPN components by splitting on the # sign.
I would be doing something along the lines of:
$container = "OU=MyOU,DC=MyDomain,DC=local"
$Filter = Read-Host -Prompt "Enter users Username/P-number"
$users = Get-ADUser -Filter "UserPrincipalName -like '$Filter#*'" -SearchBase $container
Foreach ($user in $users)
{
$null, $UPNSuffix = $user.UserPrincipalName -split '#' # Dump the first part, store the 2nd
$newFQDN = $user.GivenName + "." + $user.Surname
$NewDN = $user.GivenName + " " + $user.Surname
Set-ADUser -Identity $user -UserPrincipalName "$newFQDN#$UPNSuffix" -SamAccountName $newFQDN
Write-Host "User's UPN is now $newFQDN#$UPNSuffix"
}
From a quick Google it doesn't seem that there is a dedicated field for the Suffix, but I figure you could get the UserPrincipalName property and then just split on the # and grab the second element of the split:
$UPN = (Get-ADUser -Identity $user -Property UserPrincipalName).UserPrincipalName
If ($UPN) {
$UPNSuffix = ($UPN -Split '#')[1]
} Else {
Write-Warning "Failed to get UserPrincipalName for $User"
}
Note: this is untested code.
It's possible to get the UPN suffixes from the uPNSuffixes field in the Partitions object who's located at :
CN=Partitions,CN=Configuration,DC=xxxxx,DC=com
Thanks from this post who provide an example in C# :
List all UPN Suffixes from Active Directory
I don't know how to implement that in powershell but in PHP, it's pretty simple :
ldap_read($ldapConnection, "CN=Partitions,CN=Configuration,DC=xxxxx,DC=com", "(objectclass=*)", array("*");
Maybe with Get-UserPrincipalNamesSuffix :
https://learn.microsoft.com/en-us/powershell/module/exchange/active-directory/get-userprincipalnamessuffix?view=exchange-ps
Hope this helps someone !