Updating Active Directory Manager Attribute from .csv Using PowerShell - powershell

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

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

Set-AdUser a referral was returned from the server

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

msExchDelegateListBL attribute - The attribute cannot be modified because it is owned by the system

When attempting to clear msExchDelegateListBL for AD User then I got the following the error message.
Get-ADUser -Identity "User01" -Properties * | set-aduser -clear msExchDelegateListBL
Message :
set-aduser : The attribute cannot be modified because it is owned by the system
At line:1 char:49
+ ... ity "User01" -Properties * | set-aduser -clear msExchDelegateListBL
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (CN=User01...,DC=corp:ADUser) [Set-ADUser], ADException
+ FullyQualifiedErrorId : ActiveDirectoryServer:8369,Microsoft.ActiveDirectory.Management.Commands.SetADUser
LAST UPDATE :
$userDN = Get-ADUser -Filter {(Enabled -eq $true -and sAMAccountName -like "TEST*") -or (Enabled -eq $true -and sAMAccountName -like "PROD*")} -SearchBase "OU=COMPANY,DC=contoso,DC=local" -SearchScope Subtree -Properties * |select-object distinguishedname,samaccountname
foreach($userToClean in $userDN) {
$delegates = Get-ADUser $userToClean.samaccountname -Properties msExchDelegateListBL | select -ExpandProperty msExchDelegateListBL
Write-Host “======================================================”
write-host “List of Delegated accounts that are backlinked:” $Delegates
Write-Host “======================================================”
foreach ($delegate in $delegates) {
Set-ADUser $delegate -Remove #{msExchDelegateListLink = "$($userToClean.distinguishedname)"}
}
Write-Host “======================================================”
Write-Host “If the following get-aduser cmdlet searching for backlinds is empty, then all delegated backlinks have been removed”
Get-ADUser $userToClean.samaccountname -Properties msExchDelegateListBL | select -ExpandProperty msExchDelegateListBL
Write-Host “======================================================”
}
The msExchDelegateListBL attribute is adjusted by the system after a user is removed from (or added to) the msExchDelegateListLink of the delegate.
When users are granted permission to a shared mailbox, the default behaviour of automapping means that the shared mailbox has msExchDelegateListLink set to the DN of the users, and the backlink property (msExchDelegateLinkListBL hidden in AD by default) on each user is populated with the DN of the shared mailbox. Whenever the link attribute is updated, the backlink is automatically updated.
I found a good read about that, including PowerShell code.
For your question I suggest to scroll down to To remove all BLs all at once chapter and adapt the code in there to suit your needs as you have done in your edit.
Personally, I would change the top line in your code into
$userDN = Get-ADUser -Filter "Enabled -eq 'True'" -SearchBase "OU=COMPANY,DC=contoso,DC=local" -SearchScope Subtree |
Where-Object { $_.SamAccountName -match '^(TEST|PROD)' }
since user properties SamAccountName and DistinguishedName are returned by the Get-ADUSer cmdlet by default.

Powershell delete all users in OU

I am trying to delete all users within an OU using powershell, I have the below which gets stuck when it comes to the SAMAccount name, I want it to delete all the found users.
What am I doing wrong here please?
$search="OU=Staff,OU=Users,DC=Testing, DC=Local"
$deletes= Get-ADUser -SearchBase $search -filter * -properties SamAccountName | Select-Object SamAccountName
$numusers=($deletes.count)
echo "$numusers Users Found"
foreach ($delete in $deletes)
{
echo "Deleting user account $delete . . . "
remove-aduser -identity $delete -confirm:$false
}
This is the output. Seemingly going wrong here -- Cannot convert the "#{SamAccountName=bbonhomme}"
7 Users Found
Deleting user account #{SamAccountName=bbonhomme} . . .
Remove-ADUser : Cannot bind parameter 'Identity'. Cannot convert value "#{SamAccountName=bbonhomme}" to type
"Microsoft.ActiveDirectory.Management.ADUser". Error: "Cannot convert the "#{SamAccountName=bbonhomme}" value of type
"Selected.Microsoft.ActiveDirectory.Management.ADUser" to type "Microsoft.ActiveDirectory.Management.ADUser"."
At C:\Users\Administrator\Desktop\import\getadusers.ps1:11 char:29
+ remove-aduser -identity #delete -confirm:$false
+ ~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Remove-ADUser], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.ActiveDirectory.Management.Commands.RemoveADUser
Replace the
$deletes= Get-ADUser -SearchBase $search -filter * -properties SamAccountName | Select-Object SamAccountName
by
$deletes= Get-ADUser -SearchBase $search -filter * -properties SamAccountName
Adding Select-Object implies converting ADUser "object" to "Psobject". By consequence subsequent command remove-ADuser does not recognize this type of object.
Replace also :
remove-aduser -identity $deletes -confirm:$false
By
remove-aduser -identity $delete.SamAccountName -confirm:$false
changed $deletes by $delete (you cannot specify a collection in -Identity parameter)

ActiveDirectory change all UPN

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
}