First:
I am complete new to Powershell-Scripting.
Want to change the attribute "preferredLanguage" from some Users via powershell.
The users are written in txt-file
testUser000
testUser001 and so on
My first try was to become a list with users and some attributes:
$users = ForEach ($user in $(Get-Content C:\Temp\users.txt)) {
Get-AdUser $user -Properties Department, Mail, preferredLanguage
}
$users |
Select-Object SamAccountName,Department,Mail, preferredLanguage |
Export-CSV -Path C:\temp\outputUsers.csv -NoTypeInformation
That worked so far:
"SamAccountName","Department","Mail","preferredLanguage"
"tesUser000","dept1","testUser000#domain.com","DE"
"testUser0001","dept2","testUser001#domain.com",
testUser000 has an entry in preferredLanguage
testUser0001 has no entry
That's ok. When I have completed the users.txt, there are more than 100 users without an entry in 'preferredLanguage'
Now I want to change the preferredLanguage and with some investigation in the Internet I made this:
$users = ForEach ($user in $(Get-Content C:\Temp\users.txt)) {
Get-AdUser $user -Properties Department, Mail, preferredLanguage
}
$users |
Set-AdUser $users -Replace #preferredLanguage="DE" |
Select-Object SamAccountName,Department,Mail, preferredLanguage |
Export-CSV -Path C:\temp\outputUsers.csv -NoTypeInformation
When I understand this script right, then it get from my txt-File every user in it with the given attributes then it changes the attribute 'preferredLanguage' from the users in the txt-file and then it select it again then it will save the output in a csv-file.
Maybe someone can look over the script and would be so kind and give me feedback about it or a better way, because Iam too scary to use this script on the AD-Server.
Just a few things:
Get-AdUser $user means you must be sure the user with that identity exists or an exception will be thrown
the syntax for the -Replace operator should be #{preferredLanguage="DE"}
Set-ADUser does not generate any output unless the -PassThru parameter is used.
if you use ForEach-Object, you can do all this in one loop
Try changing the code with this:
(Get-Content C:\Temp\users.txt) | ForEach-Object {
$account = Get-AdUser -Filter "SamAccountName -eq '$_'" -Properties Department, Mail, preferredLanguage -ErrorAction SilentlyContinue
if ($account) {
$account | Set-AdUser -Replace #{preferredLanguage="DE"} -PassThru |
Select-Object SamAccountName,Department,Mail, preferredLanguage
}
else {
Write-Warning "User '$_' does not exist"
}
} | Export-CSV -Path C:\temp\outputUsers.csv -NoTypeInformation
Hope that helps
Related
I want to replace AD attribute "userPrincipalName" value according to CSV file header value
here is what csv file(group.csv) contains
sAMAccountName
--------------
test.user1
test.user2
below the script
$data = Import-Csv -Path .\group.csv -Header 'sAMAccountName'
foreach($user in $data){
Get-ADUser -Filter {sAMAccountName -eq "$($user.sAMAccountName)"} | Set-ADUser -Replace #{userPrincipalName="$($user.sAMAccountName)#RES.GROUP"}
}
here I want to replace AD attribute "userPrincipalName" with the value of sAMAccountName from csv file, something like sAMAccountName#RES.GROUP
this script does not work, can anyone please correct it?
Ok, since your comment shows the CSV file indeed does not have a header, I would suggest changing the code to:
$data = Import-Csv -Path .\group.csv -Header 'sAMAccountName'
foreach($user in $data) {
$adUser = Get-ADUser -Filter "SamAccountName -eq '$($user.sAMAccountName)'" -ErrorAction SilentlyContinue
if ($adUser) {
$newUPN = '{0}#res.group' -f $user.sAMAccountName
$adUser | Set-ADUser -UserPrincipalName $newUPN
}
else {
Write-Warning "No user with SamAccountName '$($user.sAMAccountName)' could be found.."
}
}
This way, any mistakes in the file will not make the code quit when a user with that samaccountname cannot be found. Instead, in that case you will see a warning about it and the code will continue with the rest of the data.
It might be worth mentioning that you can use parameter -Server on both the Get-ADUser and Set-ADUser cmdlets to make sure you use the same domain server (DC) to set the new UPN. Otherwise, you can set it on one DC, but are looking at another which doesn't show the change immediately because the servers need time to synchronize..
Now that we have cleared up the question about the CSV and to answer your comment:
If you want to do this as a two-script solution, here's how you can do that
step 1: get all users in the search OU that have a UserPrincipalName ending in '*#test.group'
$searchBase = "OU=Teams,OU=Prod,DC=RES,DC=TEST,DC=GROUP"
Get-ADUser -SearchBase $searchBase -Filter "UserPrincipalName -like '*#test.group'" |
# select ony the SamAccountName and write to CSV with column header
Select-Object SamAccountName | Export-Csv -Path .\group.csv -NoTypeInformation
step 2: read the csv created above and
$searchBase = "OU=Teams,OU=Prod,DC=RES,DC=TEST,DC=GROUP"
$data = Import-Csv -Path .\group.csv
$result = foreach($user in $data) {
$adUser = Get-ADUser -SearchBase $searchBase -Filter "SamAccountName -eq '$($user.sAMAccountName)'" -ErrorAction SilentlyContinue
# if we have a user object AND its UserPrincipalName is not as desired go ahead and change that
if ($adUser) {
if ($adUser.UserPrincipalName -notlike '*#res.test.group') {
$newUPN = '{0}#res.test.group' -f $user.sAMAccountName
$adUser | Set-ADUser -UserPrincipalName $newUPN
# output this user object to be collected in variable $result
$adUser
}
else {
Write-Host "User $($user.sAMAccountName) already has UPN '$($adUser.UserPrincipalName)'"
}
}
else {
Write-Warning "User with SamAccountName '$($user.sAMAccountName)' not found.."
}
}
# now that we have changed some users, create a second csv with all users that were actually changed
if (#($result).Count) {
$result | Select-Object SamAccountName | Export-Csv -Path .\Updatedgroup.csv -NoTypeInformation
}
else {
Write-Host 'No users needed updating'
}
It seems a waste writing only the users SamAccountName property to the csv files.. Especially since Get-ADUser by default already returns these properties: DistinguishedName, Enabled, GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName
I've got a simple script that works, takes in a list of user Ids and outputs a CSV with their Id, Enabled True / False, and their name. I'm trying to figure out how I can wrap into it a test where if a user is not found based on the Id in the input file, my output will include a "User [Id] is purged." or something similar.
I've been playing around but I'm not sure if I'm going to have to change my output plan to incorporate something like that. Here's what I have working, minus the check for if nothing found, write a message.
Get-Content $ENV:USERPROFILE\desktop\testusers.txt | ForEach {
Get-ADUser -Filter "SamAccountName -eq '$_'" -Properties SamAccountName,Enabled,Name |
Select SamAccountName,Enabled,Name
} | Export-CSV -path $ENV:USERPROFILE\desktop\output.csv -NoTypeInformation
If I understand correctly, you want to store users Get-ADUser cannot find as error in the output csv too.
In that case, simply try to get the user but swallow error messages and use an if{..} else {..} construct where in both cases you output objects with the same properties:
Get-Content "$env:USERPROFILE\desktop\testusers.txt" | Where-Object { $_ -match '\S' } | ForEach-Object {
$user = Get-ADUser -Filter "SamAccountName -eq '$_'" -ErrorAction SilentlyContinue
if ($user) {
# output the properties you need in the csv
$user | Select-Object SamAccountName, Enabled, Name
}
else {
# user does not exist; output a similar object with the error
[PsCustomObject]#{
SamAccountName = "User '$_' does not exist"
Enabled = $null
Name = $null
}
}
} | Export-CSV -path "$env:USERPROFILE\desktop\output.csv" -NoTypeInformation
This will display a warning for those users that could not be found.
Note, -Properties SamAccountName,Enabled,Name is not needed in this case, the 3 properties are default properties of the cmdlet.
$dom = (Get-ADRootDSE).defaultNamingContext
Get-Content $ENV:USERPROFILE\desktop\testusers.txt | ForEach-Object {
if([string]::IsNullOrWhiteSpace($_)){
continue # go to next iteration if this element is just white space
}
$usr = Get-ADUser -Filter "SamAccountName -eq '$_'" | Select SamAccountName,Enabled,Name
if(-not $usr){
Write-Warning "$_ could not be found on $dom"
continue
}
$usr
} | Export-CSV -path $ENV:USERPROFILE\desktop\output.csv -NoTypeInformation
I have a CSV file containing the samaccount name of some users.
From this list, I want to export the properties of these users to a CSV file.
Kindly share the simplest possible way to do so in Windows Powershell ISE.
I have tried this :
Import-ModuleActiveDirectory
Import-CSV C:\scripts\list.csv | ForEach{Get-ADUser -Identity $samaccountname-Filter*-Properties*|export-csv c:\ADusers.csv
}
Thank you!
You didn't show us the first couple of lines of the CSV file.
A proper CSV file has multiple fields and a header line like this:
"AccountName","EmailAddress"
"doe","john.doe#example.com"
"kent","clark.kent#example.com"
If this is the case, do:
Import-ModuleActiveDirectory
$userProperties = 'GivenName', 'SurName', 'Initials'
Import-Csv -Path "C:\Scripts\List.csv" | ForEach-Object {
$user = Get-ADUser -Filter "SamAccountName -eq '$($_.AccountName)'" -Properties $userProperties -ErrorAction SilentlyContinue
if ($user) {
$user | Select-Object -Property $userProperties
}
} | Export-Csv "C:\ADUsers.csv"
If the file you load only has SamAccountNames each listed on a new line, then this is not a CSV file and you should use:
Import-ModuleActiveDirectory
$userProperties = 'GivenName', 'SurName', 'Initials'
Get-Content -Path "C:\Scripts\List.csv" | ForEach-Object {
$user = Get-ADUser -Filter "SamAccountName -eq '$_'" -Properties $userProperties -ErrorAction SilentlyContinue
if ($user) {
$user | Select-Object -Property $userProperties
}
} | Export-Csv "C:\ADUsers.csv"
As you can see, I'm not using the -Identity parameter here, because in case a user with that SamAccountName is not found, an exception is thrown.
This way, output is only generated when the user actually exists.
Also, it is a bad idea to use -Properties * when you only want some of the properties returned.
Hope that helps
if you wanna do this in the ISE, you probably dont need/want to use oneliner for that.
I would suggest to import the CSV first, and then run foreach.
$list = Import-CSV -path $filePath
$result = New-Object System.Collections.ArrayList
foreach ($name in $list){
$adUser=Get-ADUser -Identity $name
$result += $adUser
}
From here, you can start thinking of error handling etc.
This will help you:
Import-ModuleActiveDirectory
Import-CSV -Path "C:\Scripts\List.csv" | Foreach {
Get-ADUser -Identity $_ -Filter * -Properties *
} | Export-CSV "C:\ADUsers.csv"
Your code was not working because $samaccountname was empty and blank not containing the username. So I replaced it with the automatic variable $_
Put each SamAccountName on its own line in the list file.
Example:
user1
user2
user3
Change list.csv to a text file (list.txt) and try this:
$username = Get-Content "C:\scripts\list.txt"
ForEach($user in $username){
Get-ADUser -Identity $user | Select GivenName,Surname,Initials | Export-CSV -Path "C:\ADUsers.csv"
}
There is a list of users in CSV:
Name
surname name
I want to get to their posts. I use this script:
$userList = Import-Csv "C:\Scripts\names.csv"
foreach ($User in $userList) {
Get-ADUser -Identity $user.Name -Properties DisplayName, title |
select DisplayName, title |
Export-Csv -Append "C:\Scripts\title.csv" -NoTypeInformation
}
But the script does not find users.
If you are trying to get the users by their Name or DisplayName you will have to go with Filter instead of Identity. The following should work, assuming your actual AD-users Names are in the format of the csv.
$userList = import-csv "C:\Scripts\names.csv"
ForEach($User in $userList){
Get-ADUser -Filter "Name -eq '$($user.Name)'" -Properties DisplayName,title |
select DisplayName,title | Export-CSV -Append "C:\Scripts\title.csv" -NoTypeInformation}
I'm trying to get the SAMAccountNames of one domain and compare them with their equals from another domain.
To get all users of dc1 I use:
Get-ADUser -Filter * -SearchBase $SearchBase | Select-Object SamAccountName |
Export-Csv -path $exports -encoding "unicode" -notype
and then I import the csv again and try to compare them for any differences
$readthat = Import-CSV $exports -Header SamAccountName | ForEach-Object {
$user1 = Get-ADUser -Identity $_.SamAccountName -Properties $attributes
$user2 = Get-ADUser -Identity $_.SamAccountName -Properties $attributes -Server $dc2
$modified = #{}
$attributes | Where-Object { $user1.$_ -ne $user2.$_ } | ForEach-Object {
$modified[$_] = $user2.$_
}
}
All that works great, except that it's also trying to find the SamAccountName which of course genereates an error because the SamAccountName = SamAccountName doesn't exit.
Any hints on how to avoid this or do you guys have a more elegant solution?
the .csv looks like this:
"SamAccountName"
"foo"
"bar"
Don't use the -Header SamAccountName option on your import-csv should help immensely. The -Header option is for when the CSV file you are importing doesn't have a header. The Export-CSV cmdlet puts the header in there for you, so you don't have to.