I am trying to write a powershell script that will first import from a CSV file. The CSV file will contain the AD employee number attribute, and also the business unit attribute.
The script needs to find the AD user based on employee number attribute from the CSV, then update the business unit attribute for that user also contained in the CSV file. CSV will look like:
0,1
8022651,Sales & Marketing
So far I have been able to lookup the employee number using this:
$EmployeeNumber='8022651'
get-ADUser -Filter {EmployeeNumber -eq $EmployeeNumber}
I know I can use Import-CSV, but don't know how to piece it all together. Any help would be greatly appreciated.
First we need to get the contents of the csv like so
Import-Csv "path to your csv"
If the business unit is located in the Office field we can update it with set-aduser like so
% { set-aduser $_.0 -Office $_.1 }
The % is short for foreach-object, what this essentially does is grab each user one at a time and change the Office field in AD
if we put $_ into a pipeline it will get the previous information passed through so in this case we're grabbing the "0" and "1" headers from the CSV
Once the users Office has been changed it's nice to see each change so we can use write-host like so
write-host "Changed the office of $($_.0) to $($_.1)
Once again we are using $_.0 and $_.1 to get the headings from Import-Csv but because write-host is based on a string we have to put variables into $( ) for them to display correctly.
Put together it is:
Import-Csv "path to your csv" | % {set-ADUser $_.0 -Office $_.1; write-host "Changed the office of $($_.0) to $($_.1)}
This will
Grab the information from your CSV
->then change info in Active Directory for each person based on the 0 and 1 headers
-->then write on the screen who it changed and what to
I hope this made sense, if not let me know in the comments below.
EDIT:
$csv = Import-Csv "path to your csv"
foreach($usr in $csv) {
get-ADUser -Filter {EmployeeNumber -eq $usr.0} | set-ADUser $_ -Office $usr.1
}
EDIT 2:
$csv = Import-Csv "path to your csv"
foreach($usr in $csv) {
$usrToEdit = $usr.0
$editUsr = Get-ADUser -Filter {EmployeeNumber -eq $usrToEdit}
set-aduser -Identity $editUsr.SamAccountName -Office $usr.1
}
Related
I am having difficulty using an if statement with blank cells in my CSV file. I'm attempting to write an onboarding script and have it pull info from an xlsx HR fills out (IT copies needed rows into CSV that is used in script). In order to get the OU path, I use the department names. However, some users have a sub-department and others do not, these fields are left blank in the xlsx that HR sends. I have it working by inputting a N/A in those fields however if another tech doesn't know to do that in the CSV file the script will fail. So I would like to get it working with the blank fields.
This is what im trying when not using the N/A in the CSV field
foreach ($obj in $onboardcsv){
$dep = "$($obj.department)"
$sdep = "$($obj.subDepartment)"
if ($null -eq $obj.subDepartment){
$ou = Get-ADOrganizationalUnit -Filter {name -like $dep} -SearchBase "OU=User,OU=OU,DC=DOMAIN,DC=com"
}
else{
$ou = Get-ADOrganizationalUnit -Filter {name -like $sdep} -SearchBase "OU=User,OU=OU,DC=DOMAIN,DC=com"
}
Any help would be appreciated!
To rephrase your question, you just want to search where SubDepartment isn't empty?
Without modifying too much of your code, you can make use of the static method of ::IsNullOrWhiteSpace() provided in the [string] class to evaluate against the emptiness:
Using -Not reverses the result of [string]::IsNullOrWhiteSpace($obj.subDepartment).
foreach ($obj in $onboardcsv)
{
$department = if (-not [string]::IsNullOrWhiteSpace($obj.subDepartment)) {
$obj.subDepartment
}
else {
$obj.department
}
Get-ADOrganizationalUnit -Filter "Name -like '$department'" -SearchBase "OU=User,OU=OU,DC=DOMAIN,DC=com"
}
So, testing against the subDepartment first, if $obj.subDepartment is not null, assign it to $department. This will allow the use of just one variable for both properties, and no code copying necessary.
Thanks to #Santiago for a sanity check.
Something like this would work.
$ou = "searching by sub department"
$department = if (!($user.subDepartment)) {
#subdepartment is blank
#searching by department
$ou = "searching by department"
}
$ou
I have written enough PS code to go through a list of displayNames (e.g "John Smith", "Taylor Hanson" - all stored on seperate lines of a txt file) to spit back enough data into another text file that can be used for mailmerge etc. Convincing thousands of employees to simply update Windows is like breaking stones! It has to be automatted to some degree...
Here is the code... the functions that let the user open a specific text file and later save are out of view...
$displayname = #()
$names = get-content $FileIN
foreach ($name in $names) {
$displaynamedetails = Get-ADUser -filter { DisplayName -eq $name } | Select Name, GivenName, Surname, UserPrincipalName
$displayname += $displaynamedetails
}
$displayname | Export-Csv -NoTypeInformation -path $fileOUT -Encoding UTF8
From time to time, a name might be spelled incorrectly in the list, or the employee may have left the organisation.
Is there any way that a statement such as 'Not Found' can be written to the specific line of the text file if an error is ever made (so that an easy side-by-side comparison of the two files can be made?
For most of the other solutions I've tried to find, the answers are based around the samAccoutName or merging the first and last names together. Here, i am specifically interested in displaynames.
Thanks
You can give this a try, since -Filter or -LDAPFilter don't throw any exception whenever an object couldn't be found (unless you're feeding a null value) you can add an if condition to check if the variable where the AD User object is going to be stored is not null and if it is you can add this "not found" user into a different array.
$domain = (Get-ADRootDSE).DefaultNamingContext
$names = Get-Content $FileIN
$refNotFound = [System.Collections.Generic.List[string]]::new()
$displaynamedetails = foreach($name in $names)
{
if($aduser = Get-ADUser -LDAPFilter "(DisplayName=$name)")
{
$aduser
continue
}
$refNotFound.Add(
"Cannot find an object with DisplayName: '$name' under: $domain"
)
}
$displaynamedetails | Select-Object Name, GivenName, Surname, UserPrincipalName |
Export-Csv -NoTypeInformation -path $fileOUT -Encoding UTF8
$refNotFound # => Here are the users that couldn't be found
Side note, consider stop using $displayname = #() and += for well known reasons.
As for AD Cmdlets, using scriptblock based filtering (-Filter {...}) is not supported and even though it can work, it can also bring you problems in the future.
I am trying to input a list of users into PowerShell and get a specific security group attached to the user's account. At this current time, I have two pieces - an Excel sheet with multiple pieces of data, and a .txt with just the user's usernames. The script I have currently just inputs the user's usernames from the .txt and gets the security group from their account that matches a specific prefix, however I noticed doing it this way doesn't give any specific order. Even though the users are in a specific order (copied and pasted exactly from the excel document), the actual output doesn't come back well.
So, here's what I'd Like to do now, I just don't know how. I would like to get the content from the Excel document, take all of the usernames and do Get-ADPrincipalGroupMembership like I am now, and then write the security group Back to the line that matches the username. For example, if I looked up the SG for msnow, it would get the SG for msnow and then write the SG back to the row that has msnow, and continues through the list. Instead of just doing an Out-GridView, it would actually write this to the Excel document.
Any help on making this work?
Here is the code I have right now.
Import-Module ActiveDirectory
$Names = Get-Content C:\Temp\Users.txt
$Records = #()
Foreach ($ADUsers in $Names) {
Try {
$SG = Get-ADPrincipalGroupMembership -Identity $ADUsers | Select Name | Where {$_.Name -Like "SG - *"}
$SGName = $SG.Name
}
Catch [ADIdentityNotFoundException] {
$SGName = "User not found"
}
$Records += New-Object PSObject -Property #{"UserName" = $ADUsers;"Security Group" = $SGName}
}
Write-Host "Generating CSV File..."
$Records | Out-GridView
Thank you!
If you save the Excel as CSV, so it will look something like
"UserName","Security Group","InsideInfo"
"bloggsj","","tall guy"
"ftastic","","nothing worth mentioning"
things shouldn't be that hard to do.
$out = 'D:\Test\Updated_usersandgroups.csv'
$csv = Import-Csv -Path 'D:\Test\usersandgroups.csv'
Write-Host "Updating CSV File..."
foreach ($user in $csv) {
try {
$SG = Get-ADPrincipalGroupMembership -Identity $user.UserName -ErrorAction Stop
# if more groups are returned, combine them into a delimited string
# I'm using ', ' here, but you can change that to something else of course
$SGName = ($SG | Where-Object {$_.Name -Like "SG - *"}).Name -join ', '
}
catch [ADIdentityNotFoundException] {
$SGName = "User $($user.UserName) not found"
}
catch {
# something else went wrong?
$SGName = $_.Exception.Message
}
# update the 'Security Group' value
$user.'Security Group' = $SGName
}
Write-Host "Generating updated CSV File..."
$csv | Export-Csv -Path $out -UseCulture -NoTypeInformation
# show output on screen
$csv | Format-Table -AutoSize # or -Wrap if there is a lot of data
# show as GridView (sorts by column)
$csv | Out-GridView
Output in console would then look like
UserName Security Group InsideInfo
-------- -------------- ----------
bloggsj SG - Group1, SG - Group1 tall guy
ftastic SG - Group1 nothing worth mentioning
Note: I don't know what delimiter your Excel uses when saving to CSV file. On my Dutch machine, it uses the semi-colon ;, so if in your case this is not a comma, add the delimiter character as parameter to the Import-Csv cmdlet: -Delimiter ';'
Excel uses whatever is set in your locale as ListSeparator for the delimiter character. In PowerShell you can see what that is by doing (Get-Culture).TextInfo.ListSeparator. On output, the -UseCulture switch will make sure it uses that delimiter so Excel will understand
I am trying to write a powershell script that will update employeeID attribute in AD for each user
The script needs to update employeeID from my CSV file
Sample CSV:
user,employeeID
user1,1234567
At least now you are trying some code which looks like it should work. Your logic is sound. Are you sure your CSV does not contain and blanks? Some simple statements could rule those out.
Import-CSV "C:\Scripts\Users.csv" | ForEach-Object {
$User = $_.UserName
$ID = $_.EmployeeID
If($user -and $ID){
Set-ADUser $User -employeeID $ID
} Else {
Write-Warning "User or employee number is null. Check source."
}
The If statement would fail if either $user or $id was null. If that is not the case and your CSV does contain data maybe you are having an encoding issue.
I think it depends on how you're finding the user in Active Directory... You could try something like this:
# import the users
$myUsers = Import-Csv csvFile.csv
# loop through each user and update their employeeID property
foreach ($user in $myUsers)
{
# the Set-ADUser cmdlet requires a type of System.Hashtable<>,
# so let's create one
$updateRecord = #{"EmployeeID"=$user.EmployeeID}
# Set the user attribute
Set-ADUser -Identity $user -Replace #updateRecord
}
This might do the trick. Did you guys modify the AD Schema? Keep in mind that "EmployeeID" is assuming you have an EmployeeID Attribute on your Active Directory users.
Please let me know if it helps!
I was wondering if someone could help me Importing users from a CSV or Excel file to AD based on a Templateuser. However i have no idea how to get the SamAccountNAme and Display name row for row from a CSV file so i don't have to manually change it.
$UserInstance = Get-ADuser -Identity "SaraDavis"
New-ADUser -SAMAccountName "EllenAdams" -Instance $userInstance -DisplayName "EllenAdams"
The CSV file would look something like this. Let's assume this information goes into c:\test\users.csv.
SamAccountName,DisplayName
trevor,Trevor Sullivan
nancy,Nancy Drew
billy,Billy Bob
The, script would look something like this:
# 1. Get a reference to the template user, with all properties
$TemplateUser = Get-ADUser -Identity TemplateUser -Properties *;
# 2. Import the CSV file
$Data = Import-Csv -Path c:\test\users.csv;
# 3. Create a new user for each row / item in the CSV file
foreach ($Item in $Data) {
New-ADUser -Identity $Item.SamAccountName -DisplayName $Item.DisplayName -Parameter1 $TemplateUser.Property1 ... ... ... ...;
}