Display UserName only once in csv powershell - powershell

I am having the below code which is giving me the list of ad groups a specific user is part of
Get-Content "C:\Automation Scripts\users.txt" | Get-ADUser | ForEach{
$user = $_
$groups = Get-ADPrincipalGroupMembership $user
$groups | %{ New-Object PSObject -Property #{ User = $user.SamAccountName; Group = $_.SamAccountName } }
} | Export-Csv "C:\Automation Scripts\User_Groups.csv" -NoTypeInformation
It is working fine and I am getting the result, but the result is coming like below
"User","Group"
"A92M7202822","Domain Users"
"A92M7202822","A92GS-505-Central Team Data"
"A92M7202822","A00GRP-AdminAccounts"
"A92A7803642","Protected Users"
"A92A7803642","A00GRP-AdminAccounts"
I need the result in csv like below
User,Group
A92M7202822,"Domain Users
A92GS-505-Central Team Data
A00GRP-AdminAccounts
A92GS-505-Ids-Analytics-Share-A92DFS
A92GS-505-Data-DSICF-DEV
A92GS-505-Data-DSICF-PRD
CFRGRP-FS-FR4000_SSgt_CFIDS_RW"
A92A7803642,"Domain Users
Protected Users
A00GRP-AdminAccounts"
One cell for user and next cell should have all the groups in it.
Please let me know what changes need to be done for this

Try not to use New-Object, instead you can use PSCustomobject. Also, in your script you have used $user.samaccountname as values for both User and Groups. I have replaced group name value with name you may modify it.
$output = #()
$output += Get-Content "C:\Automation Scripts\users.txt" | Get-ADUser | ForEach{
$user = $_
$groups = Get-ADPrincipalGroupMembership $user
[PSCustomObject]#{
'User'= $user.SamAccountName
'Group' = $groups.Name
}
}
$output | Export-Csv "C:\Automation Scripts\User_Groups.csv" -NoTypeInformation
And another efficient way of doing this is like:
$users = Get-Content "C:\Automation Scripts\users.txt"
$output = foreach ($user in $users)
{
$groups = Get-ADPrincipalGroupMembership $user
foreach($group in $groups)
{
[PSCustomObject]#{
User = $user
Group = $group.Name
}
}
}
$output | Export-Csv "C:\Automation Scripts\User_Groups.csv" -NoTypeInformation

Related

Import-Csv add a column then Export-Csv

I am often given a CSV and asked to add information to it. For a simplified example I may be handed the following CSV and asked to get the lastlogontimestamp for each user
In order to achieve this I did the following
$csv = import-csv users.csv
$report = "User Audit_{0:dd-MM-yyyy_HHmm}.csv" -f (Get-Date)
$csv | ForEach-Object {
$user = ""
$user = get-aduser $_.user -Properties lastlogontimestamp | Select-Object #{ N = 'LastLogonTimestamp'; E = { [DateTime]::FromFileTime($_.LastLogonTimestamp) } }
[pscustomobject]#{
User = $_.User
'First Name' = $_.'First Name'
'Last Name' = $_.'Last Name'
'LastLogonTimestamp (AD)' = $user.lastlogontimestamp
} | Export-Csv $report -NoTypeInformation -Append
}
This works very well but creating it can be time consuming for spreadsheets with lots of columns and is subject to human error during the pscustomobject construction. So my question is - rather than manually constructing the pscustomobject is there a way to code it (using the column headings to populate each key and value), after which I can append my new additions?
You can use Select-Object with * to copy all existing columns and use calculated properties to add new ones:
$report = "User Audit_{0:dd-MM-yyyy_HHmm}.csv" -f (Get-Date)
import-csv users.csv | ForEach-Object {
$user = get-aduser $_.user -Properties lastlogontimestamp
$_ | Select-Object *,
#{ N = 'LastLogonTimestamp (AD)'; E = { [DateTime]::FromFileTime($user.LastLogonTimestamp) } }
} | Export-Csv $report -NoTypeInformation
Also, as suggested by Mathias R. Jessen, move Export-Csv to the end of the pipeline and remove -Append to improve performance. Otherwise the file would be opened and closed for each row, which is very slow.
I also took the liberty to slightly refactor the code to remove the first Select-Object statement, which is no longer needed. Also you can pipe Import-Csv directly into ForEach-Object, without using a temporary variable.
Part of the reason why it's time-consuming is that you're appending your results for each user. You could reduce how long it takes by simply assigning all your results to a variable and then exporting those results to a CSV at the end like this:
$csv = import-csv users.csv
$report = "User Audit_{0:dd-MM-yyyy_HHmm}.csv" -f (Get-Date)
$results = $csv | ForEach-Object {
$user = ""
$user = get-aduser $_.user -Properties lastlogontimestamp | Select-Object #{ N = 'LastLogonTimestamp'; E = { [DateTime]::FromFileTime($_.LastLogonTimestamp) } }
[pscustomobject]#{
User = $_.User
'First Name' = $_.'First Name'
'Last Name' = $_.'Last Name'
'LastLogonTimestamp (AD)' = $user.lastlogontimestamp
}
}
$results | Export-Csv $report -NoTypeInformation
You could also ignore the variable all together and pipe your results directly to Export-Csv
$csv = import-csv users.csv
$report = "User Audit_{0:dd-MM-yyyy_HHmm}.csv" -f (Get-Date)
$csv | ForEach-Object {
$user = ""
$user = get-aduser $_.user -Properties lastlogontimestamp | Select-Object #{ N = 'LastLogonTimestamp'; E = { [DateTime]::FromFileTime($_.LastLogonTimestamp) } }
[pscustomobject]#{
User = $_.User
'First Name' = $_.'First Name'
'Last Name' = $_.'Last Name'
'LastLogonTimestamp (AD)' = $user.lastlogontimestamp
}
} | Export-Csv $report -NoTypeInformation
In terms of human error. I'm not sure what exactly is "prone to human error" in your code so I can't make a recommendation there.
UPDATE - This should get you what you're looking for
$csv | ForEach-Object {
Get-AdUser $_.user -Properties lastlogontimestamp | Select-Object UserPrincipalName, SamAccountName, GivenName, SurName, #{ N = 'LastLogonTimestamp'; E = { [DateTime]::FromFileTime($_.LastLogonTimestamp) } }
} | Export-Csv $report -NoTypeInformation

pscustomobject multiple lines per row

I have some code so far, but would like it to result in a table with multiple lines for users per group.
Currently, it creates a table like this:
Group
Users
abcgroup1
Alice
abcgroup1
Bob
abcgroup2
Bob
abcgroup2
Jason
abcgroup3
Eve
I would like it to instead create a table like this:
Group
Users
abcgroup1
AliceBob
abcgroup2
BobJason
abcgroup3
Eve
$Groups = get-adgroup -Filter 'name -like "*abc*"'
$Results = foreach( $Group in $Groups ){
Get-ADGroupMember -Identity $Group | foreach {
[pscustomobject]#{
Group = $Group.Name
Users = $_.Name
}
}
}
$Results
$Results | Export-Csv C:\abc_search.txt -NoTypeInformation
You can use -join operator concatenating by CRLF `r`n. This will result in a multiline string:
$Groups = Get-ADGroup -Filter "name -like '*abc*'"
$Results = foreach($Group in $Groups)
{
[pscustomobject]#{
Group = $Group.Name
Members = (Get-ADGroupMember -Identity $Group).Name -join "`r`n"
}
}
$Results | Format-Table -Wrap -Autosize
$Results | Export-Csv C:\abc_search.csv -NoTypeInformation
Note that I'm using -Wrap on Format-Table, needed to correctly display multiline strings on the console.
The other option you could use is Out-String thought that would also require the use of .TrimEnd() method to get rid of the trailing new line:
Members = ((Get-ADGroupMember -Identity $Group).Name | Out-String).TrimEnd()

Need to export the output to an csv

Im trying to run the below code that compares the user and group and confirms if the user is a member of the group. But i'm unable to export the output to an excel.
$users = gc .\UserInfo.csv
$groups = gc .\groupInfo.csv
$outputFilePath = "C:\Users\salesid.csv"
$members = foreach ($group in $groups) {Get-ADGroupMember -Identity $group -Recursive | Select -ExpandProperty SamAccountName
foreach ($user in $users) {
If ($members -contains $user) {
$a = write-host "$user is a member of $group"
} Else {
$a = Write-Host "$user is not a member of $group"
}
}
}
$a| Export-Csv .\Output.csv -NoTypeInformation
Read-Host -Prompt "Press Enter to exit"
To output as CSV file you can open in Excel, you need to output objects in the loop, not strings:
$users = Get-Content .\UserInfo.csv
$groups = Get-Content .\groupInfo.csv
$outputFilePath = "C:\Users\salesid.csv"
# loop through the groups; collect all output in $result
$result = foreach ($group in $groups) {
$members = Get-ADGroupMember -Identity $group -Recursive | Select-Object -ExpandProperty SamAccountName
# loop through the users array and outout objects that get collected in variable $result
foreach ($user in $users) {
[PsCustomObject]#{
Group = $group
User = $user
IsMember = ($members -contains $user) # True or False in the output
}
}
}
$result | Export-Csv -Path $outputFilePath -UseCulture -NoTypeInformation
If the amount of data is too large to handle in memory, the following code should work, BUT will be slower because of all the extra disk-write actions:
# loop through the groups
foreach ($group in $groups) {
$members = Get-ADGroupMember -Identity $group -Recursive | Select-Object -ExpandProperty SamAccountName -Unique
# loop through the users array and outout objects that get collected in variable $result
foreach ($user in $users) {
$isMember = "$user is {0}a member of $group" -f $(if ($members -contains $user) {''} else {'NOT '})
[PsCustomObject]#{
Group = $group
User = $user
IsMember = $isMember
} | Export-Csv -Path $outputFilePath -UseCulture -Append -NoTypeInformation
}
}
switch -UseCulture makes sure the delimiter character is the same your local Excel will understand. This might be the default comma, but perhaps your system uses the semi-colon as list seoarator

get list of DLs few users are member of

I am beginner in powershell and trying to create a script.
I have list of users, for them I need to know in which DLs they are added.
The problem I am facing is, it shows the list of DLs only, is there any way I can get DLs under the usernames? or a better way to accomplish this.
Note: we name all our DLs in capital letter thats why I have used "\b[A-Z0-9_]+\b" in where-object.
$users = import-csv C:\Test\users.csv | ForEach-Object {$_.users = $_.users.Trim(); $_} | Select-Object -ExpandProperty users
foreach ( $user in $users)
{get-ADPrincipalGroupMembership $user | select name |
Where-Object { $_.name -cmatch "\b[A-Z0-9_]+\b"} | Export-CSV "C:\test\output_file.csv" -NoTypeInformation -Append
}
Now I get the following outcome:
Group1
Group2
Group3
Group2
Group3
Group4
My ideal out put would be something along the lines of:
User MemberOf
---- --------
Bob Group1, Group2, Group3....
Jim Group2, Group3, Group4....
Thanks alot.
Assuming you're looking for Distribution Lists, you can tell if a group is a Security Group or a Distribution List by looking at the GroupCategory property of an ADGroup object.
Instead of looking at the user's memberOf attribute and finding out which ones are Distribution you can search for ADGroups that are GroupCategory -eq 'Distribution' where each user is a member:
$users = (Import-CSV C:\Test\users.csv | ForEach-Object {
$_.users.Trim()
}).users
$result = foreach ($user in $users)
{
$userDN = (Get-ADUser $user).DistinguishedName
$groups = Get-ADGroup -Filter "member -eq '$userDN' -and groupCategory -eq 'Distribution'"
[pscustomobject]#{
User = $user
MemberOf = $groups.Name -join ', '
}
}
$result | Export-CSV "C:\test\output_file.csv" -NoTypeInformation
If you want to use the code you already have, with this minor update you should be getting the result you are looking for:
$users = (Import-CSV C:\Test\users.csv | ForEach-Object {
$_.users.Trim()
}).users
$result = foreach ($user in $users)
{
$membership = Get-ADPrincipalGroupMembership $user |
Where-Object {
$_.name -cmatch "\b[A-Z0-9_]+\b"
}
[pscustomobject]#{
User = $user
MemberOf = $membership.Name -join ', '
}
}
$result | Export-CSV "C:\test\output_file.csv" -NoTypeInformation

Get-adgroupmember and Displaying nested group name and its members in and exported to CSV file

I found this script online. It was original designed to get all members of one security group and if there are nested group it will write to the host the nested group name and members in hierarchy form.
I tweaked it to import AD security groups from a CSV file and to export the results to CSV with table format. CSV files has two security group with both security groups has nested groups. Script will only list the users in the second security group and it doesn't list the nested security group.
CSV File format:
Groupname groupad name
test.testdl office\test.testdl test.testdl
test.testsg office\test.testsg test.testsg
Import-Module ActiveDirectory
$GroupList = #{}
$Table = #()
$Record = #{
"Name" = ""
"nested" = ""
"domain" = ""
"userName" =""
}
function Get-GroupHierarchy {
param()
$searchGroups = Import-Csv -Path C:\temp\ad1.csv
foreach ($item in $searchGroups) {
$groupMember = Get-ADGroupMember -Identity $item.Groupname |
Select-Object name, samaccountname, distinguishedName, objectClass
}
}
foreach ($member in $groupMember) {
$username = $member.samaccountname
$distinguishedName = $member.distinguishedName
$dc = [regex]::Match($distinguishedName,'DC=([^,|$]+)').Groups[1].Value
$domainuser = '{0}\{1}' -f $dc, $username
$Record."userName" = $member.samaccountname
$Record."Name" = $member.name
$Record."nested" = $member.objectclass
$Record."Domain" = $domainuser
$objRecord = New-Object PSObject -Property $Record
$Table += [array]$objrecord
if ($member.ObjectClass -eq "group") {
$GroupList.add($member.name, $member.name)
Get-GroupHierarchy $member.name
}
Get-GroupHierarchy
}
$Table | Export-Csv "C:\temp\SecurityGroups01.csv" -NoTypeInformation
Error message:
Get-ADGroupMember : Cannot validate argument on parameter 'Identity'. The
argument is null or empty. Provide an argument that is not null or empty, and
then try the command again.
At line:1 char:48
+ $groupMember = Get-ADGroupMember -Identity $item.name | Select-Object name, ...
+ ~~~~~~~~~~
I Know it has been ages since you asked this question. But i was working last week on something similar and obtained some results through some work. I saw this question here working on that piece of work and thought to share my work if it can help somebody.
$members = Get-ADGroupMember 'GroupName'
foreach ($member in $members){
if ($member.objectClass -eq 'Group')
{$NestGroupUsers = Get-ADGroupMember $member | select name, objectclass }
Else {
$hash = [pscustomobject]#{
'name' = $member.name
'objectclass' = $member.objectClass
}
$hash | Export-Csv C:\users.csv -Append -NoTypeInformation
}
}
$NestGroupUsers |Export-Csv C:\users.csv -Append -NoTypeInformation