I'm using a powershell script to try to import email addresses into Active Directory. Here is the script I'm using (full disclosure, I copied this from another post on this site):
Import-module ActiveDirectory
$Users = Import-CSV "C:\Users\Admin\Documents\HPD_Users.csv"
ForEach($User in $Users)
{
Set-ADUser -Identity $User.UserName -EmailAddress $User.Email
}
The error I'm getting is:
Set-ADUser : Cannot find an object with identity: 'Smith, John' under: 'DC=abc,DC=wxyz,DC=com'.
At C:\Users\Admin\Documents\Import_AD_Email.ps1:5 char:5
+ Set-ADUser -Identity $User.UserName -EmailAddress $User.Email
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Smith, John:ADUser) [Set-ADUser], ADIdentityNotFoundException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,Microsoft.ActiveDirectory.Management.Commands.SetAD
User
I think the issue is that we have the users in a specific OU. How do I specify that in the script?
Like Santiago mentioned, looks like the issue here is that $User.UserName is actually the DisplayName attribute in Active Directory.
The best and most performant way to do this would be to run it against the sAMAccountName - but if all you have access to is the DisplayName in your CSV, you could try something along these lines instead;
Import-module ActiveDirectory
$Users = Import-CSV "C:\Users\Admin\Documents\HPD_Users.csv"
ForEach($User in $Users)
{
$ADUser = Get-ADUser -Filter { DisplayName -like $User.UserName } -Properties DisplayName
Write-Host "Updating email for [$($ADUser.DisplayName)] to [$($User.Email)]"
#Set-ADUser $ADUser -EmailAddress $User.Email -WhatIf
}
Finally got it to work using sAMAccountName. Here was my final script:
Import-module ActiveDirectory
$Users = Import-CSV "C:\Users\Admin\Documents\HPD_Users3.csv"
ForEach($User in $Users)
{
Set-ADUser -Identity $User.sAMAccountName -EmailAddress $User.Email
}
And my CSV file looked like this:
Email,sAMAccountName
john.smith#abc.com,jsmith
jane.doe#abc.com,jdoe
Related
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
I'm trying to set a new company value for users from a CSV.
I read that you get the error when not setting the server in my Set-AdUser command.
At line:18 char:18
+ ... $query | Set-ADUser -Server tstdc01 -Company "New Company"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (CN=testUser\, H...DC=domain,DC=local:ADUser) [Set-ADUser], ADReferralException
+ FullyQualifiedErrorId : ActiveDirectoryServer:8235,Microsoft.ActiveDirectory.Management.Commands.SetADUser
--------------------------------------------------------------------------------------------------------
Import-Module ActiveDirectory
$users = Import-Csv -Path "pathToCsv.csv" -Encoding UTF8 -Delimiter ";"
$setUsers = #()
$domain = "domain.local:3268"
foreach ($user in $users) {
$samAccountName = $user.samAccountName
$query = Get-ADUser -Filter {Samaccountname -eq $samAccountName} -Server $domain
if ($query) {
$query | Set-ADUser -server tstdc01-Company "New Company"
$setUsers += $query
}
}
As Santiago implied this looks like an issue of cross domain or forest communication. And/or you are passing a user from one domain and attempting to set it in another.
See here, and a link here
An aside, a few pointers; You don't need to filter for samAccountName when you already have the samAccountName, the query can be something like:
$setUsers =
Get-ADUser $samAccountName -Server $domain |
ForEach-Object{
Set-ADUser $_ -Server tstdc01 -Company "New Company" -PassThru
}
Also note: you should avoid += I don't know how big a job this is, but it can degrade performance as it causes the creation of a new array and a copy of the existing array. Repeated many times that can cause big performance issues. There are a number of ways to address that, but the preferred approach is to let PowerShell gather the results for you. So above assign the $setUsers variable to the output of the loop. Add -PassThru to output the object that was set.
Update:
With the point regarding += demonstrated, #SantiagoSquarzon pointed out we don't even need the loop anymore:
$setUsers =
Get-ADUser $samAccountName -Server $domain |
Set-ADUser -Server tstdc01 -Company "New Company" -PassThru
I'm not so good at PowerShell. I have this script which worked before that I've have used to update the manager attribute in Active Directory, however, now after just replacing the file its no longer working
$Users = Import-CSV C:\Documents\Managers.csv
ForEach ($User in $Users) {
$user= Get-ADUser -Filter "displayname -eq '$($Users.EmployeeFullName)'"|select -ExpandProperty samaccountname
$manager=Get-ADUser -Filter "displayname -eq '$($Users.'Line Manager Fullname')'"|select -ExpandProperty DistinguishedName
Set-ADUser -Identity $user -Replace #{manager=$manager}
}
when running the script it returns:
Set-ADUser : Cannot validate argument on parameter 'Identity'. The argument is null. Provide a valid value for the argument, and then try running the command again.
At line:6 char:22
+ Set-ADUser -Identity $user -Replace #{manager=$manager}
+ ~~~~~
+ CategoryInfo : InvalidData: (:) [Set-ADUser], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.SetADUser
the "EmployeeFullName" and "Line Manager FullName" format in the .csv is set as i.e. joe bloggs, see below CSV file example.
EmployeeFullname Line Manager Fullname
---------------- ---------------------
Kieran Rhodes Tracey Barley
Lewis Pontin Tracey Barley
Lizzy Wilks Rodney Bennett
I also noticed if I remove and try to retype "$Users.EmployeeFullName" it no longer picks up the "EmployeeFullName" from the csv file.
Anyone know what I'm doing wrong here please?
Below would be an example:
$Users = Import-CSV C:\Documents\Managers.csv
ForEach ($User in $Users) {
$user = Get-ADUser -Filter "displayname -eq '$($User.EmployeeFullName)'"
$manager = (Get-ADUser -Filter "displayname -eq '$($User.'Line Manager Fullname')'").DistinguishedName
Set-ADUser -Identity $User -Replace #{manager=$manager}
}
Note: you don't need to dig down to the samAccountName property because Set-ADUser will take the full fidelity object for the -Identity argument. You also don't need to use Select... -ExpandProperty you can just parenthetically dot reference the distinguishedName property.
Also you can use the instancing capability in the AD cmdlets:
$Users = Import-CSV C:\Documents\Managers.csv
ForEach ( $User in $Users )
{
$User = Get-ADUser -Filter "displayname -eq '$($User.EmployeeFullName)'" -Properties Manager
$Manager = (Get-ADUser -Filter "displayname -eq '$($User.'Line Manager Fullname')'").DistinguishedName
$User.Manager = $Manager
Set-ADUser -Instance $User
}
In this case you call back the Manager property set it with a simple assignment statement than give the $User variable as the argument to the -Instance parameter of Set-ADUser
I am working on a custom script to add some custom attributes from our Exchange online to our local AD.
I have an issue passing the value into AD using the set-aduser command:
#Set UPN of current user from CSV
$UPN = $User.aduser
#Get user's MSOL object
$User = get-msoluser -UserPrincipalName "$UPN#domain.com"
#Get a list of additional email addresses for the user
$userproxies = $user.ProxyAddresses
#Find same user's local AD Object
$LocalADUser = Get-ADUser -Filter {userPrincipalName -eq $user.UserPrincipalName} -Properties * -server Server
#set custom attributes
$CustomAttr1 = get-mailbox $upn | Select-Object CustomAttribute1
$CustomAttr2 = get-mailbox $upn | Select-Object CustomAttribute2
$CustomAttr3 = get-mailbox $upn | Select-Object CustomAttribute3
#Copies properties from MSOL to Local AD Object (minus the ProxyAddresses)
Set-ADUser -server Server -DisplayName $User.DisplayName -Identity $LocalADUser.SamAccountName -Office $User.Office -Company $User.CompanyName -Department $User.Department -Title $User.title -MobilePhone $User.Mobile -OfficePhone $User.TelephoneNumber
#For each ProxyAddress in the users MSOL Object
foreach ($Proxy in $UserProxies)
{
#Add the ProxyAddress to the users Local AD Object
set-ADUser -server Server -Identity $LocalADUser.SamAccountName -Add #{Proxyaddresses=$Proxy}
}
Set-ADUser -server Server -Identity $LocalADUser.SamAccountName -add #{CustomAttribute1=$CustomAttr1}
Set-ADUser -server Server -Identity $LocalADUser.SamAccountName -add #{CustomAttribute2=$CustomAttr2}
Set-ADUser -server Server -Identity $LocalADUser.SamAccountName -add #{CustomAttribute3=$CustomAttr3}
I am failing with the last 3 lines. (-add #(CustomAttribute1=$CustomAttr1} etc.)
I get the following error
Set-ADUser : Invalid type 'System.Management.Automation.PSObject'.
Parameter name: CustomAttribute1
At C:\Users\user\Documents\AD Azure Sync.ps1:51 char:13
+ Set-ADUser -server Server -Identity $LocalADUser.SamA ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (Username:ADUser) [Set-ADUser], ArgumentException
+ FullyQualifiedErrorId :
ActiveDirectoryCmdlet:System.ArgumentException,Microsoft.ActiveDirectory.Management.Commands.SetADUser
Any suggestions on how to resolve, or even improve this?
I would like to convert the custom attribute section into an array and pass it in in a for-each loop, if possible.
I have to change all UPN in my Active Directory. Some UPN are completely empty an some are filled.
Now I want to fill them all with their sAMAccountName.
My script looks like this:
# Import AD Module
Import-Module ActiveDirectory
# Import CSV into variable $userscsv
#$userscsv = import-csv C:\temp\rename\usernames.csv
$users = Import-Csv -Path C:\temp\rename\usernames.csv
# Loop through CSV and update users if the exist in CVS file
foreach ($user in $users) {
#Search in specified OU and Update existing attributes
Get-ADUser -Filter "sAMAccountName -eq '$($user.samaccountname)'"
Set-ADUser -userPrincipalName $($users.samaccountname)
}
I get an errorcode:
Get-ADUser : Der Suchfilter wurde nicht erkannt
Bei C:\TEMP\RENAME\User-Rename.ps1:13 Zeichen:12
+ Get-ADUser <<<< -Filter "sAMAccountName -eq '$($user.samaccountname)'"
+ CategoryInfo : NotSpecified: (:) [Get-ADUser], ADException
+ FullyQualifiedErrorId : Der Suchfilter wurde nicht erkannt,Microsoft.ActiveDirectory.Management.Commands.GetADUser
Does anyone have an idea?
I would not recommend setting the UPN to the SamAccountName. That's not how it's supposed to be.
If you must do it anyway, you can't use subexpressions in a filter. Assign the value to a variable and use that in the filter expression. You also need to pipe the user object into Set-ADUser to give the cmdlet something to work with:
foreach ($user in $users) {
$acct = $user.SamAccountName
Get-ADUser -Filter "sAMAccountName -eq '$acct'" |
Set-ADUser -userPrincipalName $acct
}