# PowerShell script to update Active Directory

**URL:** <https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747>\
**Category:** PowerShell Help\
**Created:** [March 11, 2024, 12:01pm UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747 "2024-03-11T12:01:32Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![magarpol](https://avatars.discourse-cdn.com/v4/letter/m/13edae/32.png) [@magarpol](https://forums.powershell.org/u/magarpol)\
**Post date:** [March 11, 2024, 12:01pm UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/1 "2024-03-11T12:01:32Z")

</div>

Hi all, I’m trying to write a script for PowerShell, the script should read from a .csv sheet and update Active Directory if there are any changes. Somehow I don’t get what’s failing, I’m not an expert to be honest.

```auto
# Import the CSV file
$csvData = Import-Csv -Path 'C:\mydata.csv'

# Loop through each row in the CSV
foreach ($row in $csvData) {
    # Retrieve user information from the CSV
    $vorname = $row.'Vorname (bürgerlich)'
    $nachname = $row.'Nachname (bürgerlich)'
    $abteilung = $row.'Abteilung'
	$position = $row.'Position'
	$mobil = $row.'Telefonnummer (geschäftlich)'
	
    # Construct the SamAccountName from Vorname and Nachname
    $samAccountName = $vorname + ' ' + $nachname
	
	Write-Host "SamAccountName: '$samAccountName'"

    # Query Active Directory to retrieve the user object
    $user = Get-ADUser -Identity $SamAccountName -Properties Vorname, Nachname, Abteilung, Position, Mobil

    # Compare user attributes and update AD if necessary
if ($user) {
    if ($user.Vorname -ne $vorname) {
        Set-ADUser -Identity $samAccountName -Vorname $vorname -WhatIf
    }
    if ($user.Nachname -ne $nachname) {
        Set-ADUser -Identity $samAccountName -Nachname $nachname -WhatIf
    }
    if ($user.Abteilung -ne $abteilung) {
        Set-ADUser -Identity $samAccountName -Abteilung $abteilung -WhatIf
    }
    if ($user.Position -ne $position) {
        Set-ADUser -Identity $samAccountName -Position $position -WhatIf
    }
    if ($user.Mobil -ne $mobil) {
        Set-ADUser -Identity $samAccountName -Mobil $mobil -WhatIf
    }
}
    else {
        Write-Host "User with SamAccountName '$samAccountName' not found in Active Directory."
    }
}

#Press any key before closing the PowerShell window
Write-Host "Press any key to close this window..."
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')

```

Right now I have the following error:

`User with SamAccountName ' ' not found in Active Directory.`

---

<div class="post-metadata">

**Author:** ![Olaf](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/olaf/32/992_2.png) [@Olaf](https://forums.powershell.org/u/Olaf)\
**Post date:** [March 11, 2024, 1:09pm UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/2 "2024-03-11T13:09:16Z")

</div>

magarpol,  
Welcome to the forum. 👋🏼

Do the sAMAccountNames of your users in your AD really have spaces in it? … and consist of the complete firstname AND lastname?

> [@magarpol](#):
>
> `$samAccountName = $vorname + ' ' + $nachname`

> [@magarpol](#):
>
> User with SamAccountName ’ ’ not found in Active Directory.

Do you get this error only once or as often as you have data sets in your input CSV file?

---

<div class="post-metadata">

**Author:** ![magarpol](https://avatars.discourse-cdn.com/v4/letter/m/13edae/32.png) [@magarpol](https://forums.powershell.org/u/magarpol)\
**Post date:** [March 11, 2024, 1:24pm UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/3 "2024-03-11T13:24:12Z")

</div>

Hi, thanks for your reply. The account name is somehow a combination of both name and surname, but on the csv file that nomenclature doesn´t appear at all, only name and surname appear. I can take a look and see if I can export the .csv with a proper username on it.

---

<div class="post-metadata">

**Author:** ![magarpol](https://avatars.discourse-cdn.com/v4/letter/m/13edae/32.png) [@magarpol](https://forums.powershell.org/u/magarpol)\
**Post date:** [March 11, 2024, 1:44pm UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/4 "2024-03-11T13:44:50Z")

</div>

Ok I changed the script as I found another filed for complete name (which is name and surname) in the .csv export. It looks like this now:

```auto
# Import the CSV file
$csvData = Import-Csv -Path 'C:\sheet.csv'

# Loop through each row in the CSV
foreach ($row in $csvData) {
    # Retrieve user information from the CSV
    $vorname = $row.'Vorname (bürgerlich)'
    $nachname = $row.'Nachname (bürgerlich)'
	$name = $row.'Name (bevorzugt)'
    $abteilung = $row.'Abteilung'
	$position = $row.'Position'
	$mobil = $row.'Telefonnummer (geschäftlich)'
	
    # Construct the SamAccountName from Vorname and Nachname
    $samAccountName = $name
	
	Write-Host "SamAccountName: '$samAccountName'"

    # Query Active Directory to retrieve the user object
    $user = Get-ADUser -Identity $SamAccountName -Properties Vorname, Nachname, Name, Abteilung, Position, Mobil

    # Compare user attributes and update AD if necessary
if ($user) {
    if ($user.Vorname -ne $vorname) {
        Set-ADUser -Identity $samAccountName -Vorname $vorname -WhatIf
    }
    if ($user.Nachname -ne $nachname) {
        Set-ADUser -Identity $samAccountName -Nachname $nachname -WhatIf
    }
	if ($user.Nname -ne $name) {
        Set-ADUser -Identity $samAccountName -Name $name -WhatIf
    }
    if ($user.Abteilung -ne $abteilung) {
        Set-ADUser -Identity $samAccountName -Abteilung $abteilung -WhatIf
    }
    if ($user.Position -ne $position) {
        Set-ADUser -Identity $samAccountName -Position $position -WhatIf
    }
    if ($user.Mobil -ne $mobil) {
        Set-ADUser -Identity $samAccountName -Mobil $mobil -WhatIf
    }
}
    else {
        Write-Host "User with SamAccountName '$samAccountName' not found in Active Directory."
    }
}

#Press any key before closing the PowerShell window
Write-Host "Press any key to close this window..."
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')

```

Now at least read from the file, good, but I see some errors:

```auto
SamAccountName: 'John Lennon'
Get-ADUser : Mindestens eine Eigenschaft ist ungültig.
Parametername: Vorname
In C:\script.ps1:20 Zeichen:13
+ $user = Get-ADUser -Identity $SamAccountName -Properties Vorname, ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (John Lennon:ADUser) [Get-ADUser], ArgumentException
    + FullyQualifiedErrorId : ActiveDirectoryCmdlet:System.ArgumentException,Microsoft.ActiveDirectory.Management.Comm
   ands.GetADUser

User with SamAccountName 'John Lennon' not found in Active Directory.

```

---

<div class="post-metadata">

**Author:** ![Olaf](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/olaf/32/992_2.png) [@Olaf](https://forums.powershell.org/u/Olaf)\
**Post date:** [March 11, 2024, 3:11pm UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/5 "2024-03-11T15:11:30Z")

</div>

The `sAMAccountName` of an Active Directory account is a very specific and across the domain a **unique** attribute. The same goes for the `DistinguishedName`. I’d recommend using one of them to be able to clearly identify the desired accounts. ☝🏼 ☝🏼

The `name` attribute can exist multiple times in a domain. It only has to be unique across the OU. Using this attribute can lead to errors that are difficult to identify.

Where do you get the input data from? If you get it from someone else you should insist of getting at least one unique attribute. If you create it yourself you should read the `sAMAccountName` from the AD.

---

<div class="post-metadata">

**Author:** ![mrfloppy](https://avatars.discourse-cdn.com/v4/letter/m/43a26b/32.png) [@mrfloppy](https://forums.powershell.org/u/mrfloppy)\
**Post date:** [March 11, 2024, 7:21pm UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/6 "2024-03-11T19:21:07Z")

</div>

Check your CSV.  
There are several fields in AD related to name.  
GivenName (First name)  
Surname (Last name)  
Name (Surname, GivenName)  
Samaccountname (Can vary, but generally is a shortened Username)

Eg.,  
GivenName - John  
Surname - Doe  
Name - Doe, John  
Samaccountname - Doej, jdoe (really just depends on your naming convenention)

The first 3 names in this scenario are NOT names you can use to find with get-aduser -identity.

So what Olaf said, ask for samaccountname, or if you’re doing it yourself, pull the samaccountname when populating the CSV.

---

<div class="post-metadata">

**Author:** ![magarpol](https://avatars.discourse-cdn.com/v4/letter/m/13edae/32.png) [@magarpol](https://forums.powershell.org/u/magarpol)\
**Post date:** [March 12, 2024, 6:06am UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/7 "2024-03-12T06:06:30Z")

</div>

Hi, thanks for your reply.

I think the problem is that the .csv doesn´t have Samaccountname field at all. The .csv is exported from our Human Resources portal and though there are a lot of fields to be selected for the export, Samaccountname is none one of them. I tried to do it via email address as is unique as well, but it doesn´t work.

I guess is not other way to do it? ☹

---

<div class="post-metadata">

**Author:** ![Olaf](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/olaf/32/992_2.png) [@Olaf](https://forums.powershell.org/u/Olaf)\
**Post date:** [March 12, 2024, 7:45am UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/8 "2024-03-12T07:45:26Z")

</div>

> [@magarpol](#):
>
> there are a lot of fields to be selected for the export, Samaccountname is none one of them.

It may have another name. Do they have “_logon name_” or “_windows user name_” or something like this?

> [@magarpol](#):
>
> I tried to do it via email address as is unique as well, but it doesn´t work.

It does actually. You just have to use the parameter `-Filter` instead of `-Identity`.

Depending on your configuration you could use the `UserPrincipalName` with the parameter `-Identity`. In most companies this unique AD attribute is set equal to the email address.

---

<div class="post-metadata">

**Author:** ![magarpol](https://avatars.discourse-cdn.com/v4/letter/m/13edae/32.png) [@magarpol](https://forums.powershell.org/u/magarpol)\
**Post date:** [March 12, 2024, 8:40am UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/9 "2024-03-12T08:40:18Z")

</div>

Cool, many thanks for your reply. I have changed the line and now it looks like:

```auto
$samAccountName = $mail

$user = Get-ADUser -Filter {samAccountName -eq $samAccountName} -Properties givenName, sn, displayName, department, title, mobile, mail

```

Now at least I don´t see any errors at all, but

`User with samAccountName 'email@host.de' not found in Active Directory.`

---

<div class="post-metadata">

**Author:** ![Olaf](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/olaf/32/992_2.png) [@Olaf](https://forums.powershell.org/u/Olaf)\
**Post date:** [March 12, 2024, 10:27am UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/10 "2024-03-12T10:27:25Z")

</div>

> [@magarpol](#):
>
> `$samAccountName = $mail`

This is unnecessary.

> [@magarpol](#):
>
> User with samAccountName ‘email@host.de’ not found in Active Directory.

Again … The sAMAccountName is a specific attribute in AD and is usually NOT equal to the email address. In most environments I know of it is set equal to the `UserPrincipalName`.

But since the email address is usually unique in an AD as well you can use a filter like this:

```auto
$user = Get-ADUser -Filter "mail -eq '$mail'" -Properties givenName, sn, displayName, department, title, mobile, mail

```

I did a mistake … I have to correct myself:

> [@Olaf](#):
>
> Depending on your configuration you could use the `UserPrincipalName` with the parameter `-Identity`.

That is wrong. For the parameter `-Identity` you only can use:

- A distinguished name
- A GUID (objectGUID)
- A security identifier (objectSid)
- A SAM account name (sAMAccountName)

Here you can read more about:

> **[Get-ADUser (ActiveDirectory)](https://learn.microsoft.com/en-us/powershell/module/activedirectory/get-aduser?view=windowsserver2022-ps#-identity)**
>
> Use this topic to help manage Windows and Windows Server technologies with Windows PowerShell.

---

<div class="post-metadata">

**Author:** ![magarpol](https://avatars.discourse-cdn.com/v4/letter/m/13edae/32.png) [@magarpol](https://forums.powershell.org/u/magarpol)\
**Post date:** [March 12, 2024, 11:28am UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/11 "2024-03-12T11:28:46Z")

</div>

testing several things right now. Main problem is that the .csv file doesn´t have a SamAccountName field at all, as it comes from a Human Resources portal. I tried your both suggestion and they throw the same errors as before. With the one before, I can´t see errors at least, just that “not found in Active Directory” which is funny because is the email address and it´s on AD 100%.

Maybe the problems are in my “if”?

---

<div class="post-metadata">

**Author:** ![Olaf](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/olaf/32/992_2.png) [@Olaf](https://forums.powershell.org/u/Olaf)\
**Post date:** [March 12, 2024, 12:15pm UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/12 "2024-03-12T12:15:46Z")

</div>

> [@magarpol](#):
>
> Maybe the problems are in my “if”?

What “if”? Please share the code you’re using.

---

<div class="post-metadata">

**Author:** ![magarpol](https://avatars.discourse-cdn.com/v4/letter/m/13edae/32.png) [@magarpol](https://forums.powershell.org/u/magarpol)\
**Post date:** [March 12, 2024, 12:20pm UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/13 "2024-03-12T12:20:29Z")

</div>

```auto
# Import the CSV file
$csvData = Import-Csv -Path 'C:\mydata.csv'

# Loop through each row in the CSV
foreach ($row in $csvData) {
    # Retrieve user information from the CSV
    $vorname = $row.'Vorname (bürgerlich)'
    $nachname = $row.'Nachname (bürgerlich)'
	$name = $row.'Name (bevorzugt)'
    $abteilung = $row.'Abteilung'
	$position = $row.'Position'
	$mobil = $row.'Telefonnummer (geschäftlich)'
	$mail = $row.'E-Mail'
	
    # Construct the SamAccountName from user´s email
    $samAccountName = $mail
	
	Write-Host "SamAccountName: '$samAccountName'"

    # Query Active Directory to retrieve the user object
    #$user = Get-ADUser -Identity $samAccountName -Properties givenName, sn, displayName, department, title, mobile, mail
	$user = Get-ADUser -Filter {samAccountName -eq $samAccountName} -Properties givenName, sn, displayName, department, title, mobile, mail

    # Compare user attributes and update AD if necessary
if ($user) {
    if ($user.givenName -ne $vorname) {
        Set-ADUser -Identity $samAccountName -givenName $vorname -WhatIf
    }
    if ($user.sn -ne $nachname) {
        Set-ADUser -Identity $samAccountName -sn $nachname -WhatIf
    }
	if ($user.displayName -ne $name) {
        Set-ADUser -Identity $samAccountName -displayName $name -WhatIf
    }
    if ($user.department -ne $abteilung) {
        Set-ADUser -Identity $samAccountName -department $abteilung -WhatIf
    }
    if ($user.title -ne $position) {
        Set-ADUser -Identity $samAccountName -Position $position -WhatIf
    }
    if ($user.mobile -ne $mobil) {
        Set-ADUser -Identity $samAccountName -mobile $mobil -WhatIf
    }
	if ($user.mail -ne $mail) {
        Set-ADUser -Identity $samAccountName -mail $mail -WhatIf
    }
}
    else {
        Write-Host "User with samAccountName '$samAccountName' not found in Active Directory."
    }
}

#Press any key before closing the PowerShell window
Write-Host "Press any key to close this window..."
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')

```

---

<div class="post-metadata">

**Author:** ![Olaf](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/olaf/32/992_2.png) [@Olaf](https://forums.powershell.org/u/Olaf)\
**Post date:** [March 13, 2024, 12:23am UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/14 "2024-03-13T00:23:14Z")

</div>

I thought we already agreed on dropping the use of the sAMAccountName!? 😏

You’re using the wrong filter and your code is quite inefficient. In the worst case you’re calling the cmdlet `Set-ADUser` 6 times for each single user account you have in your input CSV. ☝🏼  
Instead you should use a hashtable and splatting. This way you can assemble the desired attribute depending on the existing values in the AD and call `Set-ADUser` only once.

```auto
$NotFoundList = @()

Foreach($row in $CSVData){

    $User = Get-ADUser -Filter "mail -eq '$($row.'E-mail')'" -Properties DisplayName, Department, Title, Mobile, Mail

    $SetADUserSplatHash = @{
        Identity = $User.sAMAccountName
    }

    if ($user) {
        if ($user.GivenName -ne $($row.'Vorname (bürgerlich)')) {
            $SetADUserSplatHash.Add('GivenName',$($row.'Vorname (bürgerlich)'))
        }
        if ($user.Surname -ne $($row.'Nachname (bürgerlich)')) {
            $SetADUserSplatHash.Add('Surname',$($row.'Nachname (bürgerlich)'))
        }
	    if ($user.DisplayName -ne $($row.'Name (bevorzugt)')) {
            $SetADUserSplatHash.Add('DisplayName',$($row.'Name (bevorzugt)'))
        }
        if ($user.Department -ne $($row.Abteilung)) {
            $SetADUserSplatHash.Add('Department',$($row.Abteilung))
        }
        if ($user.Title -ne $($row.Position)) {
            $SetADUserSplatHash.Add('Position',$($row.Position))
        }
        if ($user.Mobile -ne $($row.'Telefonnummer (geschäftlich)')) {
            $SetADUserSplatHash.Add('Mobile',$($row.'Telefonnummer (geschäftlich)'))
        }
        Set-ADUser @SetADUserSplatHash -WhatIf
    }
    else {
        $NotFoundList += $row
    }
}

$NotFoundList

```

Outputting verbose information during the runtime with `Write-Host` slows your code down as well. Either you should use `Write-Verbose` wich you only enable on demand. Or you simply collect the unavailable accounts in a list and output this list later on or use it to create a response for the department provided that input data.

Here you can read more about hastables and splatting:

> **[about Hash Tables - PowerShell](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_hash_tables?view=powershell-7.4)**
>
> Describes how to create, use, and sort hashtables in PowerShell.

> **[about Splatting - PowerShell](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_splatting?view=powershell-7.4)**
>
> Describes how to use splatting to pass parameters to commands in PowerShell.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex019/uploads/powershell/original/1X/385e4f9fe133561ad30a814262fe0e0ae6bc3ef0.png) [@system](https://forums.powershell.org/u/system)\
**Post date:** [April 12, 2024, 12:23am UTC](https://forums.powershell.org/t/powershell-script-to-update-active-directory/23747/15 "2024-04-12T00:23:59Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
