About importing manager attribute to AD from a CSV - powershell

I'm trying to import manager attribute to active directory for set of users using the following CSV file template
GivenName Surname DisplayName Department Title mail MobilePhone Manager SamAccountName
John Smith John Smith IT IT Manager john#example.com 1234 Mark Ebert JohnS
I used the below script and but it throws out an error.What i'm thinking it is due to manager attribute required to be in distinguished name format and **but i cannot change the csv manager column name as it comes from a different program.**The manager name in the CSV file shows in first name and last name format. What i need is to import the data on it to AD like the way it is.Any alternative methods available for this scenario.Here is the example script i used.
# Import AD Module
Import-Module ActiveDirectory strong text
$users = Import-Csv -Path C:\temp\MergedTo_AD.csv
foreach ($user in $users)
{Get-ADUser -Filter "SamAccountName -eq '$($user.samaccountname)'" | Set-ADUser -GivenName $($User.GivenName) -Surname $($User.Surname) -DisplayName $($User.DisplayName) -title $($User.title) -EmailAddress $($User.EmailAddress) -MobilePhone $($User.MobilePhone) $User -manager $ID }

If your CSV looks like this:
GivenName,Surname,DisplayName,Department,Title,mail,MobilePhone,Manager,SamAccountName
John,Smith,John Smith,IT,IT Manager,john#example.com,1234,Mark Ebert,JohnS
Joe,Bloggs,Joe Bloggs,Marketing,Administrative Assistant,joe#example.com,87954,,JoeB
Then you can see that in the second example the Manager property is empty.
To best deal with columns that could be empty, use Splatting for properties that are present in the CSV, while omitting empty fields:
Something like this:
$users = Import-Csv -Path C:\temp\MergedTo_AD.csv
foreach ($user in $users) {
# first try and find the user object in AD
$adUser = Get-ADUser -Filter "SamAccountName -eq '$($user.SamAccountName)'" -Properties Manager -ErrorAction SilentlyContinue
if ($adUser) {
# we have a valid user. create a splatting Hashtable to use with Set-ADUser
# Leave out the Manager for now, as we first need to make sure we can actually find a DN for this property.
$userProps = #{
# take out any properties you do not want to (re) set
GivenName = $user.GivenName
Surname = $user.Surname
DisplayName = $user.DisplayName
Title = $user.Title
EmailAddress = $user.mail
MobilePhone = $user.MobilePhone
}
# try and get the manager object from the $user.Manager column which may or may not have been set
if (![string]::IsNullOrWhiteSpace($user.Manager)) {
# try and find an AD user with the given DisplayName. You could also try with the `Name` property
$manager = Get-ADUser -Filter "DisplayName -eq '$($user.Manager)'" -ErrorAction SilentlyContinue
if ($manager) {
# add the 'Manager' entry to the Hashtable for properties to set
$userProps['Manager'] = $manager.DistinguishedName
}
else {
Write-Warning "Could not find '$($user.Manager)' in AD.."
}
}
else {
Write-Warning "Manager column for user '$($user.SamAccountName)' is empty.."
}
# here we set the properties to the user according to the CSV file
Write-Host "Updating user properties for '$($user.SamAccountName)'"
$adUser | Set-ADUser #userProps
}
else {
Write-Warning "User '$($user.SamAccountName)' could not be found.."
}
}

I'm not a scripting expert at all.I amended the script as below as per your suggestion.
# Import AD Module
Import-Module ActiveDirectory
$users = Import-Csv -Path C:\temp\MergedTo_AD.csv
{Get-ADUser -Filter "SamAccountName -eq '$($user.samaccountname)'" $FirstName,$LastName = (-split $User.Manager).Trim() $ID = (Get-ADUser -LDAPFilter "(&(GivenName=*$FirstName*)(SurName=*$LastName*))").SamAccountName (Get-ADUser -LDAPFilter "(&(GivenName=*$FirstName*)(SurName=*$LastName*))").SamAccountName| Set-ADUser -GivenName $($User.GivenName) -Surname $($User.Surname) -DisplayName $($User.DisplayName) -title $($User.title) -EmailAddress $($User.EmailAddress) -OfficePhone $($User.OfficePhone) -MobilePhone $($User.MobilePhone) -manager $($User.manager) }
I'm getting below error
Get-ADUser : The search filter cannot be recognized
At C:\Temp\PowershellScript-Users Import.ps1:5 char:128
+ ... im() $ID = (Get-ADUser -LDAPFilter "(&(GivenName=*$FirstName*)(SurNam ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-ADUser], ADException
+ FullyQualifiedErrorId : ActiveDirectoryServer:8254,Microsoft.ActiveDirectory.Management.Commands.GetADUser

I've reviewed the code and the reason it fails is because you cannot add the manager using the variable '$ID' is that it has no reference, nor does it resolve to the managers active directory user account. Your choices are either add the managers Distinguished Name to your csv file or stick it in your code to resolve the managers Distinguished Name.
#Import CSV File to set variable for the user’s logon name of whom manager’s field needs to be filled + delimiter
$users = Import-Csv -Delimiter ";" -Path "C:\temp\MergedTo_AD.csv"
foreach ($user in $users) {
#The Managers AD Sam Account Name
$ManagersaMACCount = "saMACcount"
#The Managers AD Distinguished Name
$ManagerID = (Get-ADUser -identity $ManagersaMACCount).DistinguishedName
#Example of Setting User's Manager Attribute -Example below
#Get-aduser -identity $user | Set-ADUser -Manager $ManagerID
#Using your code to filter AD Sam Accounts Based on column samaccountname in the csv file
Get-ADUser -Filter "SamAccountName -eq '$($user.samaccountname)'" `
#Pipe Set Users GivenName Based on column GivenName
| Set-ADUser -GivenName $($User.GivenName) `
#Set Users Surname Based on column Surname
-Surname $($User.Surname) `
#Set Users Display Name Based on column DisplayName
-DisplayName $($User.DisplayName) `
#Set Users Title Based on column Title
-title $($User.title) `
#Set Users Email Address Based on column EmailAddress
-EmailAddress $($User.EmailAddress) `
#Set Users Mobile Phone Based on column MobilePhone
-MobilePhone $($User.MobilePhone) `
#Set Users Manager Based on the Distinguished Name Attribute In Active Directory
-manager $ManagerID
}

Related

Updating Active Directory Field from Csv

Giving myself a fun little project today I thought, but now it's grown into an issue and the solution eludes me. I have a massive .Csv file with all our employees sAMAccountName and telephoneNumber attributes. I would like to update all of the telephone numbers in our active directory. I was poking around some of my old scripts, taking parts and pieces that would work for this my first iteration got me too here.
$Users = Import-Csv -Path C:\Results\EmployeeExtsTest.csv
ForEach ($User in $Users) {
$User = $User.sAMAccountName
$telephoneNumber = $User.telephoneNumber
Get-ADUser -Identity $User | Set-ADUser -telephoneNumber $telephoneNumber
}
That's when I discovered that PowerShell doesn't have a -telephoneNumber attribute. So I did some digging and then arrived here.
$Users = Import-Csv -Path C:\Results\EmployeeExtsTest.csv
ForEach ($User in $Users) {
$User = $User.sAMAccountName
$telephoneNumber = $User.telephoneNumber
Get-ADUser -Identity $User | Set-ADUser -Add #{telephoneNumber=$telephoneNumber}
}
I tested it out with my user at first and I keep getting the following.
Set-ADUser : Cannot validate argument on parameter 'Add'. The argument is null or an element of the argument collection contains a null value.
At line:6 char:50
+ ... -Identity $User | Set-ADUser -Add #{telephoneNumber=$telephoneNumber}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Set-ADUser], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.SetADUser
I know that it's reading my .Csv correctly because I can call it just fine. It outputs the following.
sAMAccountName telephoneNumber
-------------- ---------------
zgroven 1121
I know this solution "should" be easy but it's completely escaping me!
To expand on #PaulWain answer. Active Directory Users and Computers displays Telephone Number, the AD Attribute is telephoneNumber, but Set-ADUser oddly uses the parameter OfficePhone for setting it. Another quirk due to OfficePhone being a "special" field, when clearing with Set-ADUser you actually have to use telephoneNumber as the field. e.g.:
$Users = Import-Csv -Path C:\Results\EmployeeExtsTest.csv
ForEach ($UserEntry in $Users) {
$User = Get-ADUser -Filter "samAccountName -like '$($UserEntry.sAMAccountName)'" -Properties *
#Check to see if the user exists
if($User)
{
#Check to see if the Office Phone number has been cleared in CSV
if ([string]::IsNullOrEmpty($UserEntry.telephoneNumber))
{
#Clear the user's OfficePhone (telephoneNumber) in Active Directory
Set-ADUser -Identity $User -Clear telephoneNumber
}
else
{
#Update the user in Active Directory
Set-ADUser -Identity $User -OfficePhone $UserEntry.telephoneNumber
}
}
else
{
Write-Host "User $($UserEntry.sAMAccountName) does not exist in Active Directory"
}
}
One thing I add to my script is to use the -Filter parameter on my Get-ADUser that way I can verify the user exists without Get-ADUser throwing an error. See my answer for more information "Determine If Users Are In Active Directory With PowerShell":
The other method is to modify all of the properties all at once, and then use the Set-ADUser -Instance parameter to set them all at once (note: OfficePhone/telephoneNumber are special and have to be cleared manually like the above code, other fields can be manually cleared/set blank):
$Users = Import-Csv -Path C:\Results\EmployeeExtsTest.csv
ForEach ($UserEntry in $Users) {
$User = Get-ADUser -Filter "samAccountName -like '$($UserEntry.sAMAccountName)'" -Properties *
#Check to see if the user exists
if($User)
{
#Check to see if the Office Phone number has been cleared in CSV
if ([string]::IsNullOrEmpty($UserEntry.telephoneNumber))
{
#Clear the user's OfficePhone (telephoneNumber) in Active Directory
Set-ADUser -Identity $User -Clear telephoneNumber
}
else
{
#Modify Local instance of the user's properties
$User.OfficePhone = $UserEntry.telephoneNumber
}
#Modify Local instance of other user's properties
$User.GivenName = $UserEntry.GivenName
$User.Surname = $UserEntry.Surname
#..... etc.....
#Update the user in Active Directory
Set-ADUser -Instance $User
}
else
{
Write-Host "User $($UserEntry.sAMAccountName) does not exist in Active Directory"
}
}
I believe that you are being misled by what is displayed and what the actual name of the property is, due to behind-the-scenes aliasing.
Try using this instead:
set-aduser $user -OfficePhone $telephoneNumber
The final script that got me through this is here
$Users = Import-Csv -Path C:\Results\EmployeeExts.csv
ForEach ($U in $Users) {
$User = $U.sAMAccountName
$telephoneNumber = $U.telephoneNumber
Set-ADUser $User -OfficePhone $telephoneNumber
}
Because I work for a school district I will be adding on more to this in the future to look for employees that are missing. As it stands now this script just updated nearly 1000 AD accounts perfectly (aside from the missing employees that have left). I want to thank all of you for helping in giving me pieces of this answer. You've made me better at my job.
Special thanks to #PaulWain and #HAL9256

Importing csv data into custom attribute in Active Directory

I have a .csv file that I am using to modify custom attributes on users in Active Directory, but PowerShell does not like the script:
Import-Csv -path c:\users\user\desktop\doc.csv | ForEach-Object {
Set-ADUser $_.mail -replace #{
ExtensionAttribute1 = $_.ExtensionAttribute1
}
}
I get the following error:
Set-ADUser : replace
At line:2 char:4
Set-ADUser $_.mail -replace #{
CategoryInfo: InvalidOperation: (user123:ADUser) [Set-ADUser], ADInvalidOperationException
FullyQualifiedErrorId: ActiveDirectoryServer:0,Microsoft.ActiveDirectory.Management.Commands.SetADUser
The CSV only has 2 columns:
extensionAttribute1,mail
Any help would be appreciated
The -Identity parameter for Set-ADUser does not take an email address.
It needs either the DistinguishedName, objectGUID, SID or SamAccountName. You can also pipe a user object directly to the cmdlet.
Because of that, you need to first try to find the user with Get-ADUser and if that succeeds set the attribute.
Import-Csv -Path 'c:\users\user\desktop\doc.csv' | ForEach-Object {
$user = Get-ADUser -Filter "EmailAddress -eq '$($_.mail)'" -ErrorAction SilentlyContinue
if ($user) {
$user | Set-ADUser -Replace #{ extensionAttribute1 = $_.extensionAttribute1 }
}
else {
Write-Warning "No user with email address '$($_.mail)' found.."
}
}
PS. I always use the exact LDAP name inside the Hash for the key name when using -Add, -Replace etc. Case sensitive.

Powershell Active Directory Scripting - Bulk disable with change of display name

I am looking for assistance in creating/completing a Powershell script that grabs a user's samAccountName from a .csv file, disables that user in a specific domain, e.g. "foo.bar", and then prepends their AD display name with a single character. This is a bulk disable script, and it has to add that single character to the front/beginning of their display name.
What I have so far is:
Import-Module ActiveDirectory
$Server = read-host "Enter Domain to query/domain controller"
Import-Csv "C:\Temp\samAccountNames.csv" | ForEach-Object {
$samAccountName = $_."samAccountName"
Get-ADUser -Server $Server -Identity $samAccountName | Disable-ADAccount
}
Now, what I need to do is to prepend the display name with the '#' character.
(e.g. "Doe, John" becomes "#Doe, John")
You need to check if the user can be found at all first, then update the displayname and disable the account
Import-Module ActiveDirectory
$characterToPrepend = '#' # the character you want to prepend the DisplayName with
$Server = Read-Host "Enter Domain to query/domain controller"
Import-Csv "C:\Temp\samAccountNames.csv" | ForEach-Object {
$ADUser = Get-ADUser -Server $Server -Filter "SamAccountName -eq '$($_.samAccountName)'" -Properties DisplayName -ErrorAction SilentlyContinue
if ($ADUser) {
# test if the user is not already disabled
if (!$ADUser.Enabled) {
Write-Host "User '$($_.samAccountName)' is already disabled"
}
else {
$newDisplayName = $characterToPrepend + $ADUser.DisplayName
# set the new displayname and disable the user
$ADUser | Set-ADUser -DisplayName $newDisplayName -Enabled $false
}
}
else {
Write-Warning "User '$($_.samAccountName)' does not exist"
}
}
I'm using -Filter to get the user rather than the -Identity parameter because the latter will throw an exception when a user with that SamAccountName could not be found

How do I get my script to use full names to find AD account?

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

Add users into AD group with correct CSV output

I am trying to add an AD group into user profiles based on an OU
I had a similar script working, so tried to modify it and failed. I am guessing it's the " -Identity $_" it maybe, but I am not good enough to debug.
#Create a new class to hold the info for our CSV entry
Class CSVEntry{
[String]$UserName
[String]$GroupName
[String]$TimeStamp
}
#Creating a list to hold the CSV entries
$Results = New-Object 'System.Collections.Generic.List[PSObject]'
#Defined the name of the group here
$GroupName = 'GROUPS NAME'
$ou = 'ou=XX,ou=XX,ou=XX,dc=XX,dc=local'
Get-ADUser -Filter * -SearchBase $ou | ForEach-Object{
#Add the user to the group here
Add-ADPrincipalGroupMembership -MemberOf $GroupName Identity $_
#Write-Host $_.Name - $groupName
#Build a custom CSVEntry object and add it to the list
$newRecord = [CSVEntry]::new()
$newRecord.UserName = $_.Name
$newRecord.GroupName = $groupName
$newRecord.TimeStamp = Get-Date
#Add the new record to the list
$Results.Add($newRecord)
}
#Export the list of CSV entries
$Results | Export-Csv C:\PS\AddADGroupToUsers.csv
errors:
Add-ADPrincipalGroupMembership : A positional parameter cannot be found that accepts argument 'CN=NAME,OU=XX,OU=XX,OU=XX,OU=XX,DC=XX,DC=LOCAL'.
At line:18 char:5
+ Add-ADPrincipalGroupMembership -MemberOf $GroupName Identity $_
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Add-ADPrincipalGroupMembership], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.ActiveDirectory.Management.Commands.AddADPrincipal
GroupMembership
EDIT:
So, the script doesn't actually do any changes, the group doesn't get added to the users. the output on screen is:
WARNING: User is already a member of group XYZ
WARNING: User is already a member of group XYZ
WARNING: User is already a member of group XYZ
UserName GroupName TimeStamp
-------- --------- ---------
shows ok XYZ 14/10/2019 14:50:23
shows ok XYZ 14/10/2019 14:50:23
shows ok XYZ 14/10/2019 14:50:23
All I have changed is the group name to XYZ and username shows ok in the second half. But, shows blank in the top, and I assure you that a) the user isn't already in the group and b) the script isn't adding them
Current tweaked code, warts and all but sanitised:
$groupName = 'GROUP'
$ou = 'setcorrectly'
$cred = Get-Credential -credential dom\usr
$results = Get-ADUser -Filter * -SearchBase $ou -Credential $cred | ForEach-Object {
#Add the user to the group here
try {
Add-ADGroupMember -Identity $groupName -Members $_.DistinguishedName -Credential $cred -ErrorAction Stop
}
catch {
Write-Warning "User $($_.Name) is already a member of group $groupName"
}
# output a PsCustomObject that gets collected in the $results variable
[PsCustomObject]#{
'UserName' = $_.Name
'GroupName' = $groupName
'TimeStamp' = Get-Date
}
}
# output on console
$results | Format-Table -AutoSize
# Export to CSV file
$results | Export-Csv C:\PS\AddADGroupToUsers.csv -NoTypeInformation
Read-Host -Prompt "Press Enter to exit"
CSV output shows the second half of the screen output only, and doesn't say anything is already a member
Below uses Add-ADGroupMember to add user(s) to 1 group instead of Add-ADPrincipalGroupMembership which is used to add 1 user to multiple groups.
It also uses [PsCustomObject]s to output the results, so you don't need to use the Class CSVEntry.
# Define the name of the group here.
# can be either:
# A distinguished name
# A GUID (objectGUID)
# A security identifier (objectSid)
# A Security Account Manager account name (sAMAccountName)
$groupName = '<NAME OF THE GROUP>'
$ou = 'ou=XX,ou=XX,ou=XX,dc=XX,dc=local'
$results = Get-ADUser -Filter * -SearchBase $ou | ForEach-Object {
#Add the user to the group here
$userName = $_.Name
try {
Add-ADGroupMember -Identity $groupName -Members $_.DistinghuishedName -ErrorAction Stop
# output a PsCustomObject that gets collected in the $results variable
[PsCustomObject]#{
'UserName' = $_.Name
'GroupName' = $groupName
'TimeStamp' = Get-Date
}
}
catch {
Write-Warning "User $userName is already a member of group $groupName"
}
}
# output on console
$results | Format-Table -AutoSize
# Export to CSV file
$results | Export-Csv C:\PS\AddADGroupToUsers.csv -NoTypeInformation
Edit
If you want the $results variable to ALSO contain users that are already a member of the group, you could simply move the creation of the [PsCustomObject] below the catch{..} block:
$results = Get-ADUser -Filter * -SearchBase $ou | ForEach-Object {
#Add the user to the group here
$userName = $_.Name
try {
Add-ADGroupMember -Identity $groupName -Members $_.DistinghuishedName -ErrorAction Stop
$status = "User added successfully"
}
catch {
Write-Warning "User $userName is already a member of group $groupName"
$status = "User is already a member"
}
# output a PsCustomObject that gets collected in the $results variable
[PsCustomObject]#{
'UserName' = $userName
'GroupName' = $groupName
'TimeStamp' = Get-Date
'Status' = $status
}
}
Hope that helps