Export Distribution Group - powershell

I need to export the following to a csv or excel file
-Distribution Group (PrimarySmtpAddress)
-Distribution Group members and each primarysmtpaddress
I tried adding
Group email: $($group) | PrimarySmtpAddress
in the code below but it does not add it.
#This is what works but is missing
$groups = Get-DistributionGroup -ResultSize Unlimited | Select -ExpandProperty name
ForEach ($group in $groups)
{
"Group Name: $($group)`nGroup Members:`n"
Get-DistributionGroupMember $group |ft name,alias,primarysmtpaddress
}
I am missing the Distribution group primary smtp address?

As Lee_Daily commented, you are stripping out all properties except the Name by doing Select -ExpandProperty name. Next, if you want to export to a CSV file, DO NOT USE Format-Table (ft), because that is only to format the result to the console.
What you should do is create an array of objects and pipe that to the Export-Csv cmdlet, like in the below (untested) code:
$outputFile = '<PATH AND FILENAME FOR THE EXPORTED CSV FILE>'
Get-DistributionGroup -ResultSize Unlimited | ForEach-Object {
# The Identity parameter for Get-DistributionGroupMember specifies the distribution group
# or mail-enabled security group. You can use any value that uniquely identifies the group.
# The cmdlet also accepts the Identity parameter as pipeline input, so
# $_ | Get-DistributionGroupMember will also work.
$Members = Get-DistributionGroupMember -Identity $($_.PrimarySmtpAddress)
foreach ($member in $Members) {
[PSCustomObject]#{
GroupName = $_.DisplayName
GroupAlias = $_.Alias
GroupEmail = $_.PrimarySMTPAddress
MemberName = $member.DisplayName
MemberEmail = $member.PrimarySMTPAddress
# Maybe also add RecipientType to distinguish between users and groups?
# MemberType = $member.RecipientType
}
}
} | Export-Csv -Path $outputFile -NoTypeInformation
Hope that helps

Related

list users that are not part of a few distribution lists PowerShell Exchange online

I'm looking to find users whos primary smtp is our domain.com that are not part of certain office365 distribution lists we have. For example Dist1, Dist2, Dist3, Dist4. I'm not very good with PowerShell but I found this script and I'm hoping someone can help me adjust this.
This script pulls the group membership of all groups.
Get-Mailbox | Where-Object {$_.PrimarySMTPAddress -like "*domain.com"} | ForEach-Object {
$user = Get-User -Identity $_.DistinguishedName
$groups = Get-Group | Where-Object {$_.Members -contains $User}
$_ | Select-Object DisplayName, Alias, PrimarySMTPAddress,
#{Name = 'Groups' ; Expression = {$groups.Name -join '; '}}
} | Export-Csv -Path 'X:\O365UserGroups.csv' -NoTypeInformation
I have made a script that checks if users whos primary smtp is your domain.com and if they are members of distributionsgroup 1 or 2. If the user is not a member of a distributionsgroup it will output this. You can add export to csv etc easily yourself.
$Users = Get-Mailbox | ? {$_.PrimarySmtpAddress -like "*domain.com"} #Enter your domain
$DistributionGroups = #("dist1","dist2") #Enter names of your distributiongroups
foreach($DistributionGroup in $DistributionGroups)
{
$DistributionGroupMembers = Get-DistributionGroupMember $DistributionGroup
foreach($User in $Users)
{
foreach($DistributionGroupMember in $DistributionGroupMembers)
{
if($DistributionGroupMember.PrimarySmtpAddress -ne $User.PrimarySmtpAddress)
{
Write-Host "$($User.PrimarySmtpAddress) missing in $DistributionGroup" #Export output here fx.
}
}
}
}

Exchange/Powershell - Add data to new column rather than joining

I am trying to export list of users in mail enabled security groups to csv but want to have each member in a separate column rather than joining the existing column.
$Csvfile = "C:\SPOgroupmembers.csv"
$Groups = Get-DistributionGroup -Filter "Alias -like '*.spo'" -ResultSize Unlimited
$Groups | ForEach-Object {
$GroupDN = $_.DistinguishedName
$DisplayName = $_.DisplayName
$PrimarySmtpAddress = $_.PrimarySmtpAddress
$Members = Get-DistributionGroupMember $GroupDN -ResultSize Unlimited
[PSCustomObject]#{
DisplayName = $DisplayName
PrimarySmtpAddress = $PrimarySmtpAddress
Members = ($Members.Name -join ',')
}
} | Sort-Object DisplayName | Export-CSV -Path $Csvfile -NoTypeInformation -Encoding UTF8 #-Delimiter ";"
This is how it currently outputs:
DisplayName
PrimarySmtpAddress
Member
Test.SPO
Test.SPO#test.com
User1,User2,User3
This is what I am trying to achieve:
DisplayName
PrimarySmtpAddress
Test.SPO
Test.SPO#test.com
User1
User2
I may be missing something simple but any help would be appreciated
If you want to export the data where each member has it's own row, which in my opinion, would be the proper way to do it, you can have an inner loop to create a new pscustomobject per member of the Group:
Get-DistributionGroup -Filter "Alias -like '*.spo'" -ResultSize Unlimited | ForEach-Object {
foreach($member in Get-DistributionGroupMember $_.DistinguishedName -ResultSize Unlimited) {
[PSCustomObject]#{
DisplayName = $_.DisplayName
PrimarySmtpAddress = $_.PrimarySmtpAddress
Member = $member
}
}
} | Sort-Object DisplayName | Export-CSV -Path ....
The simplest way to construct a [pscustomobject] dynamically is to construct an ordered hashtable first - which is easy to extend iteratively - and cast it to [pscustomobject] when done.
However, in the context of creating CSV output, you need to commit to a fixed number of properties (columns) ahead of time - if feasible[1]; e.g.:
$maxMembers = 10 # <- adjust this number to the max. count of members you expect
$Groups | ForEach-Object { ...
# ...
# Initialize an ordered hashtable with the static entries...
$oht = [ordered] #{
DisplayName = $DisplayName
PrimarySmtpAddress = $PrimarySmtpAddress
}
# ... then iteratively add the Member1, Member2, ... entries
foreach ($i in 1..$maxMembers) {
$oht["Member$i"] = $Members[$i-1]
}
# Convert to a [pscustomobject] and output
[pscustomobject] $oht
} | Sort-Object DisplayName | Export-CSV -Path $Csvfile -NoTypeInformation -Encoding UTF8
If no max. member count can / should be assumed, consider denormalizing the data by using a single member column combined with creating a separate row for each member, as shown in Santiago's helpful answer, which is unquestionably the better approach for subsequent programmatic processing of the data vs. the multi-column approach you're seeking, which may be simpler to grasp for the human observer.
[1] That is, you need to know how many members a group can have at most. You could even try to determine that count programmatically, ahead of time, but either way the resulting number may be too large to be practical.

List Members of multible AD Groups with more than 5000 Users

How could I get a List of Members on multible AD Groups with more than 5000 Users
Example:
Group1 = includes 6000 Members and Group2
Group2 = includes 7000 Members
the result of the get-adgroupmember of Group1 should 13000
how can I do that? Here I have the Problem, that it will not look in sub groups recursive will not work with get-adgroup
$group = "group1"
$ADInfo = Get-ADGroup -Identity $Group -Properties Members
$outputfile = $group
$ADInfo.Members | get-aduser | Select name, enabled, UserPrincipalName, SamAccountName
#$ADInfo.Members | get-aduser | Select name, enabled, UserPrincipalName, SamAccountName | Export-Csv c:\temp\$outputfile-member.csv -Delimiter "," -NoTypeInformation
# to show output
$members = #()
$members = $ADInfo.members
$members.count
With groups that large, it will be slow, but this should do what you want:
$groups = 'group1', 'group2' # array of group names
foreach ($group in $groups) {
Write-Host "Working on group '$group'"
$result = Get-ADGroupMember -Identity $group -Recursive | Where-Object { $_.objectClass -eq 'user' } | ForEach-Object {
Get-ADUser -Identity $_.distinguishedName | Select-Object Name, Enabled, UserPrincipalName, SamAccountName
}
# show result on screen
$result | Format-Table -AutoSize
# write to export file
$result | Export-Csv -Path "c:\temp\$group-members.csv" -NoTypeInformation
}
Hope that helps
The easiest solution would be to adjust the MaxGroupOrMemberEntries parameter in ADWS on the DC you are targeting. You can see information on ADWS defaults here.
You could do something like the following, which is potentially convoluted:
function Get-ADGroupMembers
{
param ($groupname)
Get-ADGroupMember $groupname | where ObjectClass -eq 'Group' | ForEach-Object {
$_.Name
Get-ADGroupMembers $_.Name
}
}
$maingroup = 'group1'
$subgroups = Get-ADGroupMembers $maingroup
$allGroups = #($maingroup)+#($subgroups)
$regexEscapes = $allGroups |% { [regex]::Escape($_) }
$filter = "CN=({0})" -f ($regexEscapes -join "|")
$output = foreach ($group in $allGroups) {
Get-AdGroup $group -Properties Members | Select #{n='Members';e={$_.Members -notmatch $filter}}
}
$output.Members
Explanation:
The function will list the Name property value for each recursively discovered member group.
Since the -notmatch regex operator is used in filtering, a regex match string needs to be constructed. There could be multiple groups so the | (regex OR) character needs to be used.
The [regex]::Escape method escapes all backslashes and other special regex characters that may appear in the name strings.
$output is an array of PSCustomObjects that contain the Members property. The Members property contains the DN of all members that are users.
Non-PowerShell commands may be better suited for this particular case if the ADWS default limits are not modified.

extract users from given list of groups and extract the data to every new group name in text using powershell

Facing issue in output-file commandlet while extracting user list from given list of groups. I need each time a new text file to be generated in a Text format with the name of the groups given in the content list and data which is generated each time should be in that text file.
$grp= Get-Content 'C:\Users\p731400a\Desktop\groups.txt'
$grpdata= #()
$grpname=#()
foreach($grps in $grp)
{
$grps
$data= get-qadgroupmember $grps | Select-Object samaccountname | ft -AutoSize
$grpname +=$grps
$grpdata+= $data
}
Out-File -FilePath C:\Users\p731400a\Desktop\$grps.txt -InputObject $grpdata
If in the input file the group names are stored each on a separate line, this should do it:
# read the input file as string array and loop through the list
Get-Content 'C:\Users\p731400a\Desktop\groups.txt' | ForEach-Object {
# the $_ automatic variable here represents one group name at a time
# add the `-Indirect` switch to get group members recursively when using 'Get-QADGroupMember'
$members = Get-QADGroupMember $_ -Type 'user' -Indirect |
Select-Object -ExpandProperty SamAccountName
# or use
# $members = Get-ADGroupMember -Identity $_ -Recursive |
# Where-Object { $_.objectClass -eq 'user' } |
# Select-Object -ExpandProperty SamAccountName
#output on screen:
Write-Host ("{0}`r`n{1}" -f $_, ('-' * $_.Length)) -ForegroundColor Yellow
$members
#output to file:
$members | Add-Content -Path "C:\Users\p731400a\Desktop\$_.txt"
}
Hope that helps

How to get list of selected AD Groups, that a large list of users are members of?

I have the below working script that checks if a large list of users in a CSV file are a member of an AD group and writes the results to results.csv.
Not sure how to convert the script so I can change $group = "InfraLite" to $group = DC .\List_Of_AD_Groups.CSV.
So the script doesn't just return matches for one AD group but so it returns matches for the 80 AD groups contained in the List_of_AD_groups.csv also. Writing a YES/NO for each AD group in a new column in the CSV (or if that's not possible creating a seperate .csv file for each group with results would do also.
I could do this manually by changing the value of $group and export file name, and re-running the script 80 times but must be a quick was with PS to do this?
e.g. results.csv:
NAME AD_GROUP1 AD_GROUP2 AD_GROUP80 etc etc.
user1 yes no yes
user2 no no yes
user3 no yes no
echo "UserName`InfraLite" >> results.csv
$users = GC .\user_list.csv
$group = "InfraLite"
$members = Get-ADGroupMember -Identity $group -Recursive |
Select -ExpandProperty SAMAccountName
foreach ($user in $users) {
if ($members -contains $user) {
echo "$user $group`tYes" >> results.csv
} else {
echo "$user`tNo" >> results.csv
}
}
I played with this for a while, and I think I found a way to get you exactly what you were after.
I think Ansgar was on the right path, but I couldn't quite get it to do what you were after. He mentioned that he didn't access to an AD environment at the time of writing.
Here is what I came up with:
$UserArray = Get-Content 'C:\Temp\Users.txt'
$GroupArray = Get-Content 'C:\Temp\Groups.txt'
$OutputFile = 'C:\Temp\Something.csv'
# Setting up a hashtable for later use
$UserHash = New-Object -TypeName System.Collections.Hashtable
# Outer loop to add users and membership to UserHash
$UserArray | ForEach-Object{
$UserInfo = Get-ADUser $_ -Properties MemberOf
# Strips the LPAP syntax to just the SAMAccountName of the group
$Memberships = $UserInfo.MemberOf | ForEach-Object{
($_.Split(',')[0]).replace('CN=','')
}
#Adding the User=Membership pair to the Hash
$UserHash.Add($_,$Memberships)
}
# Outer loop to create an object per user
$Results = $UserArray | ForEach-Object{
# First create a simple object
$User = New-Object -TypeName PSCustomObject -Property #{
Name = $_
}
# Dynamically add members to the object, based on the $GroupArray
$GroupArray | ForEach-Object {
#Checking $UserHash to see if group shows up in user's membership list
$UserIsMember = $UserHash.($User.Name) -contains $_
#Adding property to object, and value
$User | Add-Member -MemberType NoteProperty -Name $_ -Value $UserIsMember
}
#Returning the object to the variable
Return $User
}
#Convert the objects to a CSV, then output them
$Results | ConvertTo-CSV -NoTypeInformation | Out-File $OutputFile
Hopefully that all makes sense. I commented as much of it as I could. It would be very simple to convert to using ADSI if you didn't have RSAT installed on whatever machine you're running this on. If you need that let me know, and I'll make some quick modifications.
I've also tossed a slightly modified version of this in a Gist for later reference.
The trivial solution to your problem would be to wrap your existing code in another loop and create an output file for each group:
$groups = Get-Content 'C:\groups.txt'
foreach ($group in $groups) {
$members = Get-ADGroupMember ...
...
}
A more elegant approach would be to create a group mapping template, clone it for each user, and fill the copy with the user's group memberships. Something like this should work:
$template = #{}
Get-Content 'C:\groups.txt' | ForEach-Object {
$template[$_] = $false
}
$groups = #{}
Get-ADGroup -Filter * | ForEach-Object {
$groups[$_.DistinguishedName] = $_.Name
}
Get-ADUser -Filter * -Properties MemberOf | ForEach-Object {
$groupmap = $template.Clone()
$_.MemberOf |
ForEach-Object { $groups[$_] } |
Where-Object { $groupmap.ContainsKey($_) } |
ForEach-Object { $groupmap[$_] = $true }
New-Object -Type PSObject -Property $groupmap
} | Export-Csv 'C:\user_group_mapping.csv' -NoType