read a csv file using powershell - powershell

I'm struggling with reading and writing a csv file using power shell. I need to read a file containing three columns Servers, Users, Status
I've completed the first step (read in the file)
The next step is to split the data in the Status field by its delimiter ';' (I have that as well)
Now where the problem comes in is where I loop thru a Get-ADUser and build the print line putting all the values in the foreach loop together - seperated with a ';'. (new status field)
Then of course at the conclusion write out the completed file.
so the input file is a csv that contains the following
Server Users Status
ABC xtom
JKL
CDEA msall;jbec
The output csv would be
Server Users Status
ABC xtom xert.tom#abc.com;
JKL
CDEA msall;jbec mik.sall#abc.com;jay.bec#abc.com
my code as it stands
$List = Import-Csv -Path "c:\data\infile.csv"
$outarray = #()
foreach ($item in $List)
{
Write-output $item
$Servers= $($item.Server)
$Users = $($item.Users)
$Status = $($item.Status)
if ($Users.length -gt 0)
{
$CharArray =$Users.Split(";")
Foreach ($i in $CharArray)
{
$email = Get-ADUser -Filter {SamAccountName -like $i} | Select -Property UserPrincipalName
$outarray = $email
}
}
}
$outarray | Export-Csv "c:\data\testout.csv" -noType
Any help would be appreciated
Thanks
The csv input file
Server,Users,Status
ABC,xtom,
JKL,,
CDEA,msall;jbec,
the csv output file
Server,Users,Status
ABC,xtom,xert.com#abc.com
JKL,,
CDEA,msall;jbec,mik.sall#abc.com;jay.bec#abc.com

So, if I understand correctly what you need this code should work for you:
$List = Import-Csv -Path "c:\data\infile.csv"
$outarray = [system.collections.generic.list[pscustomobject]]::new()
foreach ($item in $List)
{
Write-output $item
$Server = $($item.Server)
$Users = $($item.Users)
$Status = $($item.Status)
if ($Users)
{
$CharArray = $Users.Split(";")
$email = $(
Foreach ($i in $CharArray)
{
$usr=(Get-ADUser -Filter {SamAccountName -like $i}).UserPrincipalName
if($usr){$usr}
}) -join ';'
}
$outarray.Add(
[PSCustomObject]#{
Server = $Server
Users = $Users
Status = $email
})
}
$outarray | Export-Csv "c:\data\testout.csv" -NoTypeInformation
It's worth mentioning that userPrincipalName is definitely not the same thing as mail even though they can look the same this may not always be the case.
Also, if $i will actually contain samAccountNames then -Filter {....} is not needed.

Related

Needing to send emails from Powershell

bit of a long one...
I have code that splits up an input, searches for a username. If it can find one - it should send an email to the technician (who is in the input as well) saying the username is ready. If it finds multiple, I need it to send a list of all the possible ones to the technician. If it can't find any, I want it to ignore that user completely. I am struggling being able to send an email from Powershell itself. Has anyone got any ideas about the below?
$list holds the information
$names = $list | ForEach-Object { $_.Split(",")[0] };
$name = $names | ForEach-Object { $_.Split("-")[1]} #Gets the actual names for the users
$emails = $list | ForEach-Object { $_.Split(",")[2]} #Gets the technician email addresses
$count = 0
foreach ($test in $name) {
$indexemails = $emails[$count]
$a,$b,$c = $test | ForEach-Object { $_.Split(" ")}
$displaynamedetails = Get-ADUser -filter {GivenName -eq $b -and Surname -eq $c} | Select-Object samAccountName
if ($displaynamedetails -eq $null) {
$count ++}
else {
$final += $displaynamedetails, $indexemails
$count ++
}}
Thank you in advance

CSV var as expression is empty, shown as {}

I got a small issue. I have a CSV with some names. I needed to get the email addresses of those users, so I created a small script that will find users with that firstname and lastname in AD.
After that, I wanted to export it to a new CSV file, but keep the phone-numbers from the first CSV file so its also available in the new CSV export.
That last part don't seem to work. In the output that expression is shown as {}.
Can someone help me?
$csv = import-csv -path C:\users\da6\desktop\UsersZonderEmail.csv
$output = #()
foreach ($i in $csv) {
$givenname = $i.Voornaam
$lastname = $i.Achternaam
$number = $i.IpPhone
$output += try {Get-ADUser -Filter {givenname -eq $givenname -and surname -eq $lastname} | select Name, UserPrincipalName, #{ name="ipphone"; expression=$number}} catch {}
}
Basically what is wrong with your code is that you forgot the opening bracket { in the expression oart of the calculated property.
Also note that -Filter should be a string, not a scriptblock.
Lastly, adding to an array with += is a bad habit, as the entire array needs to be rebuilt in memory on every addition.
Better let PowerShell collect the values from the loop:
$csv = Import-Csv -Path 'C:\users\da6\desktop\UsersZonderEmail.csv'
$output = foreach ($item in $csv) {
Get-ADUser -Filter "GivenName -eq '$($item.Voornaam)' -and Surname -eq '$($item.Achternaam)'" -Properties EmailAddress |
Select-Object Name, UserPrincipalName, #{ Name="ipphone"; Expression = {$item.IpPhone}}, EmailAddress
}
# output to new CSV file
$output | Export-Csv -Path 'C:\users\da6\desktop\UsersMetEmail.csv' -NoTypeInformation

Compare User AD and CSV file column Powershell

I'm not really good in Powershell, I try to write a script to compare a column "User" in a CSV with my all user AD.
I need to get all users in the CSV where not in our AD.
Here what I have wrote :
$csvfile = Import-CSV USERAccountstocompare.csv
$alladusers = Get-ADUser -Filter * | Select sAMAccountName
foreach($user in $alladusers){
$userAD = $alladusers.SamAccountName
foreach($usercsv in $csvfile){
if ($usercsv | where {$_.user -ne "$userAD"}){ write "$usercsv"}
else{}
}
}
When I put a write $usercsv before the if command; I get the good user
but after the if, it write all user with #{User= before, like "#{User=username}" so the comparison not working.
You don't need a foreach loop for this; just filter with Where-Object.
Assuming the User column in the CSV contains SamAccountNames:
$csvUsers = Import-Csv -Path 'D:\Test\USERAccountstocompare.csv'
$allADUsers = Get-ADUser -Filter * | Select-Object -ExpandProperty sAMAccountName
$notADUsers = $csvUsers | Where-Object { $allADUsers -notcontains $_.User }
# output on screen
$notADUsers | Format-Table -AutoSize
# output to new CSV file
$notADUsers | Export-Csv -Path 'D:\Test\UsersNOTinAD.csv' -NoTypeInformation
$alladusers = Get-ADUser -Filter * | Select sAMAccountName is not a very good idea if the Domain you are working on is big. Using Where-Object is also not a very good idea for filtering big objects, there was a really cool article in powershell.org where Dave Wyatt and Don Jones explained the different ways of filtering an object and their efficiency, sadly it was removed for some reason.
I would do something like this, assuming your Csv has a column 'User' for each user:
$result=New-Object System.Collections.ArrayList
#result array will be only the user that do not exist in AD
$csvfile = Import-CSV USERAccountstocompare.csv
foreach($line in $csvfile.User)
{
$filter="(|(Name=$line)(samAccountName=$line))"
$adusr=Get-ADuser -LDAPFilter $filter
if(!$adusr)
{
$result.add($line) > $null
}
}
If instead, you wanna have a list of the users that are on the Csv and on AD and those that are only in the Csv you could do something like this:
$result=New-Object System.Collections.ArrayList
#result array will be only the user that do not exist in AD
$csvfile = Import-CSV USERAccountstocompare.csv
foreach($line in $csvfile.User)
{
$filter="(|(Name=$line)(samAccountName=$line))"
$adusr=Get-ADuser -LDAPFilter $filter
if(!$adusr)
{
$result.add(
[pscustomobject]#{
'Not In AD'=$line
}) > $null
}
else
{
$result.add(
[pscustomobject]#{
'In AD and Csv'=$line
}) > $null
}
}

powershell - compare username to a csv and report non-matches

I'm migrating users from a legacy system into Active Directory and need to add them into an AD group. Usernames don't match (or have any logic!) between the two systems so I've got a csv with the old and new usernames in:
Input.csv:
SamAccountName,LegacyUsername
ChristopherSpraggons,CSprag
JakeSquirrell,JakeSq
GeorgeCornish,CornishG
I've written the powershell to do the lookup and add the user to the group but ideally need it to report any users that it cannot match out to a txt file so they can be done manually. I'm totally stuck on how to do this.
Here's what I have so far:
$ImportCSV = C:\TEST.csv
Import-module ActiveDirectory
$InputCSV=get-content $ImportCSV
$MatchedUsers = Import-CSV 'Input.csv' | Where{$InputCSV -match $_.LegacyUsername} | ForEach-Object {Add-ADGroupMember -Identity "ADGroupName" -Member $_.SamAccountName}
TEST.csv is just plain a list of legacy usernames with no headings.
Don't filter the CSV data before the loop. Instead, put an conditional inside the loop and add the non-matching names to a second array:
Import-Module ActiveDirectory
$legacyNames = Get-Content 'C:\TEST.csv'
$NonMatchedUsers = #()
$MatchedUsers = Import-CSV 'Input.csv' | % {
if ( $legacyNames -contains $_.LegacyUsername ) {
Add-ADGroupMember -Identity "ADGroupName" -Member $_.sAMAccountName
$_.sAMAccountName
} else {
$NonMatchedUsers += $_.sAMAccountName
}
}
I'd rename TEST.csv to something like LegacyNames.txt, though, because it isn't a CSV in the first place.
Edit: Since you want TEST.csv to be the actual input I'd suggest a slightly different approach. Load Input.csv into a hashtable (a dictionary) and make TEST.csv the input for the pipeline:
Import-Module ActiveDirectory
$mapping = #{}
Import-Csv 'Input.csv' | % { $mapping[$_.LegacyUsername] = $_.sAMAccountName }
$NonMatchedUsers = Get-Content 'TEST.csv' | % {
if ( $mapping.contains($_) ) {
Add-ADGroupMember -Identity "ADGroupName" -Member $mapping[$_]
} else {
$_
}
}
Assuming you have headers in your CSV, you should be able to use PowerShell's array methods easily without manually enumerating both CSVs repeatedly.
$ImportCSV = C:\TEST.csv
Import-Module ActiveDirectory
$InputCSV = Get-Content $ImportCSV | `
ForEach-Object {
if ($ImportCSV -notcontains $_.UserName) {
$_ | Out-File C:\MissingNames.txt -Append
} }

Writing an array to a specific csv column with powershell

I have a csv file that has a lot of data in it, with one column being a "Username" column. I created a loop to query AD and get each username and now I need to export each of those names to the specific column in the csv. After importing the csv with:
$data = Import-CSV .\data.csv
And using the loop:
foreach($user in $data)
And I use get-aduser $user -server $server and if($? -eq $true){ $user = $user + "01" }
I tried using
$data.Username | Export-CSV .\data.csv and $data.Username | out-file .\data.csv
but so far neither have worked.
You need to keep all the information in the pipeline so you can re-export the whole thing.
Try something like this:
$data | Foreach {
get-aduser $_.Username -server $server
if($? -eq $true){ $_.Username = $_.Username + "01" }
} | export-csv .\data.csv