I have this working script:
Import-CSV -Path "$home\desktop\Script\fi13.04.20.csv" | ForEach-Object {
Get-ADUser -Filter "employeeid -like '*$($_.employeeid)*'" -Properties employeeid | select employeeid,name,SamAccountName
} | Export-CSV "$home\desktop\Script\fi-san-out.csv" -Encoding UTF8 -NoTypeInformation
I give to him a CSV file with employeeid and have back file with SamAccountName...
Я даю ему файл с employeeid и получаю обратно файл with certain parameters.
And this is an improved version-
$csv = Import-CSV -Path "$home\desktop\Script\fi13.04.20.csv"
$csvOutput = "$home\desktop\Script\fi-san-out.csv"
$object = #()
foreach($employee in $csv){
$ADUserObject = Get-ADUser -Filter "employeeID -eq '$($employee.employeeID)'" -Properties samAccountName, displayName ,employeeID -ErrorAction SilentlyContinue
if($ADUserObject){
$object += New-Object psobject -Property #{
displayName = $ADUserObject.displayName
samAccountName = $ADUserObject.SamAccountName
employeeID = $ADUserObject.employeeID
}
}else{
Write-Host "No employee found for $($employee.employeeId)" -ForegroundColor Red
}
}
if($object){
$object | Select-Object displayName, samAccountName, employeeID | Export-Csv -Path $csvOutput -Delimiter "," -Encoding UTF8 -NoTypeInformation
}
The first version produces much more results because if the employeeID contains an error "for example, the employeeID in CSV 12345 and employeeID in ActiveDirectory 123456", it gives the result.
In the improved version, it throws an error with any inaccurate ID.
The question is how to change the improved version so that it produces a result even with an error(like in the example)?
I am just starting to learn PS and I wrote an improved version with the help.
Result
$csv = Import-CSV -Path "$home\desktop\Script\ID.csv"
$csvOutput = "$home\desktop\Script\tz-san-out.csv"
$object = #()
foreach($employee in $csv){
$ADUserObject = Get-ADUser -Filter "employeeID -like '*$($employee.employeeID)*'" -Properties samAccountName, displayName ,employeeID -ErrorAction SilentlyContinue
if($ADUserObject){
$object += New-Object psobject -Property #{
displayName = $ADUserObject.displayName
samAccountName = $ADUserObject.SamAccountName
employeeID = $ADUserObject.employeeID
}
}else{
Write-Host "No employee found for $($employee.employeeId)" -ForegroundColor Red
}
}
if($object){
$object | Select-Object displayName, samAccountName, employeeID | Export-Csv -Path $csvOutput -Delimiter "," -Encoding UTF8 -NoTypeInformation
}
Related
I am trying to find out the Active Directory groups all our active users are in and want to export it to a CSV file. However the following command presents garbage in the related CSV file.
This is my code failing:
Import-Module ActiveDirectory
Get-ADUser -SearchBase "CN=Users,DC=Mycompany,DC=de" -Filter * | where { $_.enabled -eq "true" } | foreach-object {
write-host "User:" $_.Name
Get-ADPrincipalGroupMembership $_.SamAccountName | foreach-object {
write-host "Member of:" $_.name | export-csv "C:\scripts\output\ad-user-with-group-memberhip.csv" -NoTypeInformation -Encoding UTF8
}
}
Any idea what am I doing wrong here?
Write-Host only writes text to the console window. It doesn't output anything useful to pipe through to Export-Csv.
Also, unless you add switch -Append, you should set the Export-Csv cmdlet as last line in the code, otherwise you will overwrite it in every iteration.
Try
with Select-Object
Import-Module ActiveDirectory
Get-ADUser -SearchBase "CN=Users,DC=Mycompany,DC=de" -Filter "Enabled -eq $true" |
Select-Object Name, #{Name = 'Groups'; Expression = {($_ | Get-ADPrincipalGroupMembership).Name -join '; '}} |
Export-Csv -Path "C:\scripts\output\ad-user-with-group-memberhip.csv" -NoTypeInformation -Encoding UTF8
or with ForEach-Object
Import-Module ActiveDirectory
$result = Get-ADUser -SearchBase "CN=Users,DC=Mycompany,DC=de" -Filter "Enabled -eq $true" |
ForEach-Object {
[PsCustomObject]#{
Name = $_.Name
Groups = ($_ | Get-ADPrincipalGroupMembership).Name -join '; '
}
}
$result | Export-Csv -Path "C:\scripts\output\ad-user-with-group-memberhip.csv" -NoTypeInformation -Encoding UTF8
I have a script I am using to update a CSV file from my AD but it is currently outputting the results with #{} in the output CSV. So when I want to output the city it outputs #{city=toronto} instead of just toronto:
$USERS = Import-Csv "C:CSV import.csv"
$newCSV =ForEach ($User in $USERS) {
$Name = $User.name
[pscustomobject]#{
id = $user.id
name = $user.nameaddress1 = (Get-ADuser -Filter "name -like '$Name'" -properties StreetAddress | Select-Object StreetAddress)
address2 = (Get-ADUser -Filter "name -like '$Name'" -properties Office | Select-Object Office)
city = (Get-ADUser -Filter "name -like '$User.Name'" -properties City | Select-Object city)
}
}
$newCSV |export-csv "C:\CSVExport.csv" -NoTypeInformation
You're over complicating it, you can query the AD User once and then construct your export object with Select-Object:
Import-Csv "C:CSV import.csv" | ForEach-Object {
$Id = $_.Id
try {
Get-ADuser $_.Name -Properties StreetAddress, Office, City |
Select-Object #{N='Id'; E={ $Id }}, Name, StreetAddress, Office, City
}
catch { Write-Warning $_.Exception.Message }
} | Export-csv "C:\CSVExport.csv" -NoTypeInformation
I have to check the lastlogon for different users.
My script queries my domain controllers to output my report, however I have an issue.
My report does not come out in descending order. I added sort-object lastlogon -descending, but the dates don't come out correctly in my file. Can you help me?
$data = #()
$DCs = Get-ADDomainController -Filter * | Select-Object -ExpandProperty name
$users =
#'
samaccountname;
user1
user2
'# | ConvertFrom-Csv -Delimiter ';'
foreach ($DC in $DCs) {
foreach($user in $users)
{$data += Get-ADUser $User.samaccountname.Trim() -Properties displayname, userprincipalname, samaccountname, lastlogon -server $DC | Select-Object DisplayName, UserPrincipalName, SamAccountName, Enabled, #{name='LastLogon';expression={[datetime]::fromFileTime($_.lastLogon).ToString('yyyy-MM-dd')}} }
}
$data | Group-Object Lastlogon | Foreach-Object {$_.Group | Sort-Object lastLogon -Descending | Select-Object -Last 10 | Export-Excel "C:\temp\lastlogon ($(Get-Date -Format "yyyy-MM-dd")).xlsx"}
write-host Done! -ForegroundColor Green
It's unclear what you want to accomplish with your script but basically, if you .ToString(..) a DateTime object then Sort-Object will not know how to sort it correctly. Here is how you can approach your code:
$DCs = (Get-ADDomainController -Filter *).Name
$users = #'
samaccountname;
user1
user2
'# | ConvertFrom-Csv -Delimiter ';'
& {
foreach ($DC in $DCs) {
foreach($user in $users) {
$params = #{
Properties = 'displayname', 'lastlogon'
Server = $DC
Identity = $User.samaccountname.Trim()
}
Get-ADUser #params | Select-Object #(
'DisplayName'
'UserPrincipalName'
'SamAccountName'
'Enabled'
#{
Name = 'LastLogon'
Expression = {
[datetime]::fromFileTime($_.LastLogon)
}
}
)
}
}
} | Group-Object { $_.Lastlogon.ToString('yyyy-MM-dd') } | Foreach-Object {
$_.Group | Sort-Object LastLogon -Descending | Select-Object -Last 10 |
Export-Excel "C:\temp\lastlogon ($(Get-Date -Format "yyyy-MM-dd")).xlsx"
}
You also want to avoid adding elements (+=) to a fixed collection (#()).
I want to get canonical name for each groups as well. how can I do that ?
Here is my script :
Get-ADUser -Filter {Enabled -eq $true} -Properties * | Select displayname ,#{Name="MemberOf";Expression={($_.MemberOf | %{(Get-ADGroup $_).sAMAccountName}) -Join ";"}} | Export-Csv -Path "c:\temp\users.csv" -NoTypeInformation -Encoding UTF8
My output :
"displayname","MemberOf"
"User01","Group01;Group02;Group03"
My desired output:
"displayname","MemberOf"
"User01","Group01;Contoso.com/OU1/OU2;Group02;Contoso.com/OU21/OU52;Group03;Contoso.com/OU1/OU21/OU22"
I agree with Mathias but this is how you can do it using the code you already have. Definitely recommend you to only call the properties that you need to query.
Get-ADUser -Filter {Enabled -eq $true} -Properties Displayname,MemberOf |
Select-Object Displayname,
#{
Name="MemberOf"
Expression={
# ($_.MemberOf | ForEach-Object{
# (Get-ADGroup $_ -Properties CanonicalName).CanonicalName
# }) -Join ";"
# You can pipe $_.MemberOf to Get-ADGroup, since it's an array of
# distinguishedNames it should work fine
($_.MemberOf | Get-ADGroup -Properties CanonicalName).CanonicalName -Join ";"
}
} | Export-Csv -Path "c:\temp\users.csv" -NoTypeInformation -Encoding UTF8
An alternative to that code, using a more classical approach:
$users = Get-ADUser -Filter {Enabled -eq $true} -Properties DisplayName
$result = foreach($user in $users)
{
$params = #{
LDAPFilter = "(member=$($user.DistinguishedName))"
Properties = "CanonicalName"
}
$membership = (Get-ADGroup #params).CanonicalName -join ";"
[pscustomobject]#{
DisplayName = $user.DisplayName
MemberOf = $membership
}
}
$result | Export-Csv -Path "c:\temp\users.csv" -NoTypeInformation -Encoding UTF8
First of all, you shouldn't be using Properties * when you only need two properties.
Then, the -Filter should be a string, not a scriptblock.
With just a small adaptation to your code, this should work:
Get-ADUser -Filter "Enabled -eq 'True'" -Properties DisplayName, MemberOf |
Select-Object DisplayName,
#{Name = "MemberOf"; Expression = {
($_.MemberOf | ForEach-Object {
($_ | Get-ADGroup -Properties CanonicalName).CanonicalName -Join ";" })
}
} |
Export-Csv -Path "c:\temp\users.csv" -NoTypeInformation -Encoding UTF8
Looking at your latest comment, I believe you want the group NAME joined with the canonicalname of the group as well.
You can do this like so:
Get-ADUser -Filter "Enabled -eq 'True'" -Properties DisplayName, MemberOf |
Select-Object DisplayName,
#{Name = "MemberOf"; Expression = {
$_.MemberOf | ForEach-Object {
$group = $_ | Get-ADGroup -Properties CanonicalName
'{0};{1}' -f $group.Name, ($group.CanonicalName -join ';')
}
}
} |
Export-Csv -Path "c:\temp\users.csv" -NoTypeInformation -Encoding UTF8
I have a list of users and I want to export their group names, sorted A-Z. The following script is not working in the inner ForEach-Object loop.
Get-Content users.txt | ForEach-Object {
$user = $_;
Get-ADUser –Identity $user –Properties MemberOf | Select-Object -ExpandProperty MemberOf | sort
ForEach-Object {
New-Object PSObject -property #{User=$user;Group=$_;}
}
} | Export-Csv -Path 'your_file_path.csv' -NoTypeInformation
The ForEach-Object is just sitting out there alone--you have to either pipe an object to it, or assign the object to a variable and use foreach to loop through the object instead. I took the second approach below as excessive piping makes scripts difficult to read (for me).
Get-Content c:\temp\users.txt | ForEach-Object {
$user = $_;
$AdUser = Get-ADUser –Identity $user –Properties MemberOf | Select-Object -ExpandProperty MemberOf | get-adgroup | select -ExpandProperty Name | sort
foreach($group in $AdUser) {
New-Object PSObject -property #{User=$user;Group=$group;} | Export-Csv -Path 'c:\temp\out.csv' -NoTypeInformation -Append
}
}
...and if you want to pipe it and use ForEach-Object, you just need to put a pipe after the sort and move the Export-Csvso that it exports the new object that was created:
Get-Content c:\temp\users.txt | ForEach-Object {
$user = $_;
Get-ADUser –Identity $user –Properties MemberOf | Select-Object -ExpandProperty MemberOf | get-adgroup | select -ExpandProperty Name | sort |
ForEach-Object {
New-Object PSObject -property #{User=$user;Group=$_;} | Export-Csv -Path 'c:\temp\out.csv' -NoTypeInformation -Append
}
}