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
Related
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.
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
}
}
I am trying to create a script that will check a list of user names and show the user full name and some attribute settings from AD. Basically I have been sent a list of usernames which are just numbers and management want to know the users full name for each username. they also want to know want division they work for.
Below is the script I have created which doesn't work.
$csv = Import-Csv "C:\temp\users.csv"
foreach ($user in $csv) {
$name = $user.myid
Get-ADUser -Filter {EmployeeID -eq $name} -Properties * |
Get-ADUser -Division $user.Programme
} | Export-Csv "C:\Temp\Results.csv"
So I'm working under the assumption that there is a column named myid in your csv file that contains the id you need to be looking up. Assuming that is the case you'll need to make a few changes here. You'll need to remove the second get-aduser as it is not really doing anything for you, and there is no -division switch available to the get-aduser cmdlet, if you need to restrict your results to just a few settings you can do that using the -properties switch and piping to select as shown below. Keep in mind that none of this will matter if the users do not have the "employeeid" and "division" properties set on their AD accounts, which is fairly rare in my experience but if your company does as a matter of policy when creating accounts should be fine. If you replace the get-aduser line in your script with this it should get the account of any user with an EmployeeID property that matches the one in your spreadsheet and then output that person's full name, division, and employeeid to your CSV file.
Get-ADUser -Filter {EmployeeID -eq $name} -Properties "displayname","division","employeeid" | Select-Object "employeeid","displayname","division"
When in doubt, read the documentation. Get-ADUser doesn't have a parameter -Division. You need to select the properties you want in the output file. Also, foreach loops don't pass output into the pipeline. You need a ForEach-Object loop if you want to pass the output directly into Export-Csv:
Import-Csv 'C:\temp\users.csv' |
ForEach-Object {
$name = $_.myid
Get-ADUser -Filter "EmployeeID -eq $name" -Properties *
} |
Select-Object SamAccountName, DisplayName, Division |
Export-Csv 'C:\Temp\Results.csv' -NoType
Otherwise you need to collect the output in a variable:
$users = foreach ($user in $csv) {
$name = $user.myid
Get-ADUser -Filter "EmployeeID -eq $name" -Properties *
}
$users | Export-Csv 'C:\Temp\Results.csv' -NoType
or run the loop in a subexpression:
$(foreach ($user in $csv) {
$name = $user.myid
Get-ADUser -Filter "EmployeeID -eq $name" -Properties *
}) | Export-Csv 'C:\Temp\Results.csv' -NoType
This is a generic code structure that can be adapted for data collection / enumeration and production of CSV files, tailored to your scenario. We use similar at my workplace. It contains some error handling - the last thing you'd want is inaccurate results in your CSV file.
# Create an array from a data source:
$dataArray = import-csv "C:\temp\users.csv"
# Create an array to store results of foreach loop:
$arrayOfHashtables = #()
# Loop the data array, doing additional work to create our custom data for the CSV file:
foreach($item in $dataArray)
{
try
{
$ADObject = Get-ADUser -Filter { EmployeeID -eq $item.MyID } -Properties DisplayName,Division -ErrorAction Stop
}
catch
{
Write-Output "$($item.MyID): Error looking up this ID. Error was $($Error[0].Exception.Message)"
}
if($ADObject)
{
# Create a hashtable to store information about a single item:
$hashTable = [ordered]#{
EmployeeID=$item.myID
DisplayName=$ADObject.DisplayName
}
# Add the hashtable into the results array:
$arrayOfHashtables += (New-Object -TypeName PSObject -Property $hashTable)
}
else
{
Write-Output "$($item.MyID): No result found for this ID."
}
}
# If the results array was populated, export it:
if($arrayOfHashtables.Count -gt 0)
{
$arrayOfHashtables | Export-CSV -Path "C:\Temp\Results.csv" -Confirm:$false -NoTypeInformation
}
As mentioned elsewhere, division isn't a property on an AD object so you might need to lookup this data elsewhere. If you can do that with another line of PowerShell inside your foreach loop, you could add this to your hashtable object like so:
$hashTable = [ordered]#{
EmployeeID=$item.myID
DisplayName=$ADObject.DisplayName
Division=$DivisionFromOtherSource
}
I have a input file(input.txt) with the following data. The below data are saved in my domain as contacts. My task is to identify the corresponding mail id in my domain for these contacts.
abcd#otherdomain.com
efgh#otherdomain.com
ijkl#otherdomain.com
Below is the powershell script I wrote to accomplish the task. The targetaddress of these contacts will be my domain email id. But the problem here is, while exporting I need the input data also to be appended to my result.
Write-Host "Reading Input File.. "
$users=""
ForEach ($contact in $(Get-Content 'Input.txt'))
{
$DomainId = Get-ADObject -Filter {(mail -eq $contact) -and (ObjectClass -eq "Contact")} -Properties * | Select targetAddress
$DomainId = $DomainId.targetAddress.remove(0,5)
$users+= (Get-AdUser -Filter {Mail -eq $DomainId} -Properties * | Select Mail)
}
Write-Host "Exporting to CSV.."
$users | Export-CSV -Path 'output.csv' -NoTypeInformation
Below is the current output (output.csv)
Mail;
ab#mydomain.com;
ef#mydomain.com;
ij#mydomain.com;
But the expected output is,
Mail;InputId;
ab#mydomain.com;abcd#otherdomain.com;
ef#mydomain.com;efgh#otherdomain.com;
ij#mydomain.com;ijkl#otherdomain.com;
Is there a possibility to get the expected output. If so, please assist. Many thanks in advance for your support.
Untested, but something like this could work:
Write-Host "Reading Input File.. "
$users = foreach ($contact in (Get-Content 'Input.txt'))
{
$DomainId = Get-ADObject -Filter {
(mail -eq $contact) -and (ObjectClass -eq "Contact")
} -Properties * | Select-Object -ExpandProperty targetAddress
$DomainId = $DomainId.Remove(0,5)
$Mail = (Get-AdUser -Filter {Mail -eq $DomainId} -Properties Mail).Mail
[PSCustomObject]#{
InputId = $DomainId
Mail = $Mail
}
}
Write-Host "Exporting to CSV.."
$users | Export-CSV -Path 'output.csv' -NoTypeInformation
You want PSCustomObjects going into Export-CSV, with one property per column. And they are easy to build by casting from a hashtable, instead of using a lot of Add-Member.
I am trying to create an "initial" text file that will hold a script run of all users + department + direct reports. My next step after making this file is to create another file the same way but compare it to the original to see if the department for the users ever changed. (not sure yet how to compare the department value just yet)
My current issue is that the department, even though the process is identical to another program I have made in the past, won't print it. Furthermore, when it prints my direct reports it prints only the first one with the whole extension of CN=..., OU=... etc.
I want it to print this way:
username | Department(extensionAttribute14) | Direct Reports (as a single string)
we38432 | IT-Security | cm03456: 04555a: ....etc
My original script used this code for department:
$deps = Get-Aduser -filter {name -like *} -Properties name, extensionAttribute14 | Select name, extensionAttribute14 | Export-CSV $listing -notypeinformation
and this worked. I tried the {name -like *} but that gave me errors in my current program. I know the Export-CSV makes it work but I can't use this format anymore.
for the direct reports my original was this:
foreach ($ID in $directReports){
if ($ID -ne $Null){
$directreports = get-aduser $ID
$directreports.name | Out-File $output -Append
}
This code printed line by line the direct reports but I want them all listed in the same excel cell when I send it there.
I have printed a listing of all the members in the past using ":" and it worked but it is not the case with the direct reports listing. I just get errors when I use this format from my other program:
foreach ($member in $empty.members){
$string = $member.substring(3,$member.indexof(",")-3)
$members = $members + ":" + $string
}
I hope someone can help me with my two issues.
Import-Module ActiveDirectory
$documentOld = "C:\Temp\Old_Supervisor_list_mo_yyyy.txt"
Clear-Content $documentOld
$Header = `
"User ID" <#+ "|" + `
"Department" + "|" + `
"Direct Reports"#>
$Header | Out-File $documentOld -Append
$Users = Get-AdUser -Filter * -Properties name, Enabled, Manager, extensionAttribute14 | Select Enabled, name, Manager, extensionAttribute14
foreach ($user in $Users){
if ($user.enabled –eq $true) {
$name = $user.name
$directReports = Get-ADUser -Identity $name -Properties directreports | Select -ExpandProperty directreports
$department = $user.extensionAttribute14
foreach ($ID in $directReports){
if ($ID -ne $Null){
$directreports = get-aduser $ID
# $string = $directreports + ":"
}#end if $ID
}#end foreach $ID
$listing = `
$name + "|" + $deparment + "|" + $directreports#$string
$listing | Out-File $documentOld -Append
}# end if
}# end foreach $user
Let see if we can make this a little easier and efficient.
Import-Module ActiveDirectory
$documentOld = "C:\Temp\Old_Supervisor_list_mo_yyyy.txt"
$Users = Get-AdUser -Filter * -Properties name,Enabled,Manager,extensionAttribute14 | Where-Object{$_.Enabled}
$Users | ForEach-Object{
$props = #{
Name = $_.Name
Department = $_.extensionAttribute14
DirectReports = ($_.Manager | Where-Object{$_} | ForEach-Object{Get-Aduser $_ | Select-object -ExpandProperty Name}) -join ":"
}
New-Object -TypeName psobject -Property $props
} | Select-Object Name,Department,DirectReports | Export-CSV -Delimiter "|" -NoTypeInformation -Path $documentOld
First we get all the users from your directory with Get-AdUser -Filter * taking all the properties outside the norm that we want. Since you just wanted accounts that are enabled we filter those out now with Where-Object{$_.Enabled}.
The fun part is creating the custom object array ( which is necessary for input for Export-CSV). Create a small hashtable called $props where we set the properties by their friendly names. The special one being DirectReports where we take all the users manager DN's ( Assuming they have one where is what Where-Object{$_} does by filtering out nulls/empty strings.) and use Get-Aduser to get there names. Since you could have more than one manager an array is most likely returned we use -join to ensure only a single string is given for the DirectReports property. That property collection is created for every user and it is then used to create a New-Object which is sent to the output stream.
The Select-Object that follows is just to ensure the order of columns in the CSV that is created. No need for making a CSV file with lots of Out-Files when Export-CSV and -Delimiter "|" will do the hard work for you.