Create dynamic members of PSObject - powershell

This is what I got:
Import-Module ActiveDirectory
$objectCollection = #()
$groups = (Get-ADGroup -Filter *)
foreach ($group in $groups) {
$groupName = ($group.SamAccountName)
$object = (New-Object –Type PSObject)
Add-Member -InputObject $object -MemberType NoteProperty –Name ($groupName) –Value ""
$groupMembers = (Get-ADGroupMember -Identity "$groupName" -Recursive |
Select-Object -ExpandProperty Name)
$object.$groupName = $groupMembers
$objectCollection += $object
}
$objectCollection | Export-Csv -Path C:\Users\administrator\Desktop\test.csv `
-Encoding UTF8 -Delimiter ";" -NoTypeInformation
The goal with this script is to create a CSV file where the AD group name is the header in one column an then all the members of the group listed below on separate lines. Next group is in a new column with the AD-group name as header and so on...
Normally I create as many Members as I need but this time I want it to be dynamic to how many groups there is and the script above only displays the first group in the $groups array.
Any help is appreciated, thanks in advance!

Having each group on a separate column in a CSV file seems illogical to me ; one on each row would IMHO be better (and easier too).
Here is how I would do it:
Import-Module ActiveDirectory
Get-ADGroup -Filter * | ForEach-Object {
[PSCustomObject]#{
Name = $_.samAccountName
Members = (Get-ADGroupMember $_ -Recursive | Select-Object -ExpandProperty Name) -join ","
}
} | Export-Csv -Path "C:\Users\administrator\Desktop\test.csv" -Encoding UTF8 -Delimiter ";" -NoTypeInformation
Output:
"Name";"Members"
"Administrators";"Administrator,..."
"Domain Users";"Administrator,TestUser,..."

Related

Export AzureAD group owners to CSV

The end goal I'm after is I want to have a csv containing the owners of all AzureAD groups.
I'm not well versed in PS and I've been trying to crack it for a while now, with various different scripts each with their own method. Things that seem logical, and I think would work, don't.
Feel free to edit what I've got or write a new script entirely, but please explain what you have done so I can learn :)
The closest I've come to what I want is using the below. But the caveat is if there are multiple owners of the group, each owner is listed out on separate rows and so there is also duplicate group names. I would like to have the group name in one column then all the owners in the next, seperated by " ,".
I tried using -join on the final line but it returns blank results.
$array = #()
$Properties=#{}
$Properties.add("GroupDisplayName","1")
$Properties.add("OwnerDisplayName","2")
$groups = Get-AzureADGroup -All $true | Where-Object DisplayName -Like "*Guest*" | Sort-Object -Property DisplayName
Foreach($group in $groups){
$Owners = Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true
$Properties.GroupDisplayName=$group.DisplayName
if($Owners -ne $null){
# group has owner
Foreach($Owner in $Owners){
$Properties.OwnerDisplayName=$Owner.DisplayName
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
else{
#group has no owner
$Properties.OwnerDisplayName=$null
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
$array | export-csv -Path C:\Temp\test123.csv -NoTypeInformation -Encoding UTF8
Thanks in advance for your help, you will save me some hair...
EDIT
This is another route I've tried. It does return results I want if using one specific ObjectID but I can't get it to loop the bunch of ObjectIds from step 1 and run the command for each one.
#Connect to AzureAD
Connect-AzureAD
#Successfully returns groups with "Guest" in DisplayName
$GroupSearch = Get-AzureADGroup -All $true | Where-Object DisplayName -Like "*Guest*" | Select-Object ObjectId, DisplayName | Sort-Object -Property DisplayName
$groups = #($GroupSearch | Select-Object ObjectID)
#Now to loop ObjectIDs from STEP 1 to lookup command
$Result = foreach ($group in $groups){
Get-AzureADGroupOwner -ObjectId "$group" | Select-Object DisplayName
}
$Result | Export-Csv -Path "C:\Temp\AzureADgroupOwners.csv" -NoTypeInformation
#Disconnect from AzureAD
Disconnect-AzureAD
Figured it out with some help from other sources. Hopefully someone will find this helpful in future! This is how:
#Connect to AzureAD
Connect-AzureAD
$Properties=#{}
$matchingOwners=#()
$groups = Get-AzureADGroup -All $true | Where-Object DisplayName -Like "*Guest*"
Foreach($group in $groups) {
$Owners = Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true
     $matchingGroup = $group.DisplayName
if ($null -ne $Owners) {
#group has owner
Foreach($Owner in $Owners) {
                $matchingOwners+=$Owner.DisplayName
}
}
$joinedOwners = $matchingOwners -join ", "
     $Properties.add($matchingGroup, $joinedOwners)
$joinedOwners=""
$matchingOwners=#()
}
$Properties.GetEnumerator() | Select-Object -Property Key,Value | Sort-Object -Property Key | export-csv -Path C:\Temp\test123.csv -NoTypeInformation -Encoding UTF8
#Disconnect from AzureAD
Disconnect-AzureAD
I tried to reproduce the same in my environment by using the below PowerShell script:
$array = #()
$Properties=#{}
$Properties.add("GroupDisplayName","1")
$Properties.add("OwnerObjectId","2")
$Properties.add("OwnerObjectType","3")
$Properties.add("OwnerUserType","4")
$Properties.add("OwnerUserPrincipalName","5")
$groups = Get-AzureADGroup -All $true
Foreach($group in $groups){
$Owners = Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true
ForEach ($Owner in $Owners){
$Properties.GroupDisplayName=$group.DisplayName
$Properties.OwnerObjectId=$Owner.ObjectId
$Properties.OwnerObjectType=$Owner.ObjectType
$Properties.OwnerUserType=$Owner.UserType
$Properties.OwnerUserPrincipalName=$Owner.UserPrincipalName
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
$array | export-csv -Path YourPath.csv -NoTypeInformation -Encoding UTF8
The above script got executed successfully as below:
The CSV file was exported with the Azure Ad Group and Group owner details like below:
Reference:
powershell - Export all Azure AD Groups and their owner to a csv file by Jim Xu

Get AD Group Members from AD using powershell

I need to find AD group members from given groups in csv file as input. the groups contains Users and Groups also. below is sample input data
I wrote the below code. for users I am getting the output (i.e. for the first entry), but for the second one, as they are groups within group, I am not able to fetch the email.
$GroupCollection= Import-csv -Path "C:\Groups.csv"
$Report = #()
Foreach($Group in $GroupCollection){
$MemberGroup=#()
$Group = $Group.'OPE DLs'
if($Group -match '#')
{
$pos = $Group.IndexOf("#")
$leftPart = $Group.Substring(0, $pos)
}
else
{
$leftPart = $Group
}
$MemberGroup = Get-ADGroupMember -identity $leftPart -recursive | Get-ADUser -Properties mail | Select-Object mail
$MemberGroups = ($MemberGroup.mail) -join "`r`n"
if($MemberGroups -ne ""){
$Out = New-Object PSObject
$Out | Add-Member -MemberType noteproperty -Name 'Contract Details' -Value $Group.'Customer subset'
$Out | Add-Member -MemberType noteproperty -Name 'Group Name' -Value $leftPart
$Out | Add-Member -MemberType noteproperty -Name 'Member Groups' -Value $MemberGroups
$Report += $Out
}
}
$Report | Sort-Object Name | FT -AutoSize
$Report | Sort-Object Name | Export-Csv -Path ‘C:\Group-MemberGroups-Report.csv’ -NoTypeInformation
Please let me know how to get the details. Is the approach is fine or there is any other way to do this.
expected output
As commented, if the object returned by Get-ADGroupMember is a group, you won't get results by piping it through to Get-ADUser, because... it is a group, not a user.
You need to loop over the results and depending on what type the object is (group, user or computer) you use either Get-ADUser or Get-ADGroup (not interested in computer objects).
Try
$Report = foreach ($Group in $GroupCollection){
$groupName = ($Group.'OPE DLs' -split '#')[0]
$groupMembers = Get-ADGroupMember -Identity $groupName -Recursive | ForEach-Object {
$adObject = $_
switch ($adObject.objectClass) {
'group' { ($adObject | Get-ADGroup -Properties mail).mail }
'user' { ($adObject | Get-ADUser -Properties EmailAddress).EmailAddress }
}
}
if (#($groupMembers).Count) {
[PsCustomObject]#{
'Group Name' = $groupName
'Contract Details' = $Group.'Customer subset'
'Member Groups' = $groupMembers -join [environment]::NewLine
}
}
}
$Report = $Report | Sort-Object 'Group Name'
$Report | Format-Table -AutoSize
$Report | Export-Csv -Path 'C:\Group-MemberGroups-Report.csv' -NoTypeInformation
Notes:
adding to an array with += is extremely wasteful because the entire array needs to be rebuilt in memory on each iteration
To take the group name as the part left of the # character, I simply use the -split operator and take the first element ([0])
To output an object, I'm using a [PsCustomObject]#{..} construct rather than the old (pre PowerShell 3.0) New-Object PSObject method

export object using Export-Csv doesn't work

I'm trying to export the username and the user's group membership (of specifc groups) to a CSV file using Export-Csv. However, I couldn't accomplish this using several approaches.
My current script works fine but the output is shown on the PowerShell console alone:
$accounts = Get-Content "C:\Scripts\getUserGroups\users.txt"
foreach ($account in $accounts) {
"$account member of:"
Get-ADPrincipalGroupMembership -Identity $account |
select Name |
Where-Object { $_.name -like 'Browsing_Group*' } |
Sort Name
}
I want to export it to a file in an ordered manner:
UserName1
group membership
UserName2
group membership
etc...
I've tried to add to a variable but probably didn't do that correctly:
$ArrList = [System.Collections.ArrayList]#()
$accounts = Get-Content "C:\Scripts\getUserGroups\users.txt"
foreach ($account in $accounts) {
$ArrList.Add($account)
$groups = Get-ADPrincipalGroupMembership -Identity $account |
select Name |
Where-Object {$_.name -like 'Browsing_group*' } |
Sort Name
$ArrList.Add($grops)
}
Might be a different approach.
You need to build custom objects in order to export the data to a CSV via Export-Csv. The 2 main ways of doing that are:
using calculated properties:
$accounts |
Select-Object #{n='Username';e={$_}}, #{n='Groups';e={
(Get-ADPrincipalGroupMembership -Identity $_ |
Select-Object -Expand Name |
Where-Object {$_ -like 'Browsing_group*' } |
Sort-Object) -join ';'
}} |
Export-Csv 'C:\path\to\output.csv' -NoType
building custom objects directly:
$accounts | ForEach-Object {
$groups = Get-ADPrincipalGroupMembership -Identity $_ |
Select-Object -Expand Name |
Where-Object {$_ -like 'Browsing_group*' } |
Sort-Object
New-Object -Type PSObject -Property #{
'Username' = $_
'Groups' = $groups -join ';'
}
} | Export-Csv 'C:\path\to\output.csv' -NoType
With PowerShell version 3 or newer you can replace New-Object with the [PSCustomObject] type accelerator:
[PSCustomObject]#{
'Username' = $_
'Groups' = $groups -join ';'
}

Get all members for groups and subgroups

good day to all.
I've been trying to get information about groups and subgroups in Active Directory
I've tried many variants like the one below,
What I essentially need is, to get a CSV of all the groups in AD that contain "infolink" in their name, and the columns I need are:
GiveName
SN
Username
Mail
Group
ManagedBy
But no matter how I put it I only get some of the things I need.
Does someone already have a bit of code that could make my life a bit easier? If so, I'd be immensely grateful.
Import-Module ActiveDirectory
$Groups = (Get-AdGroup -filter * | Where {$_.name -like "*Infolink*"} | select name -ExpandProperty name)
$Table = #()
$Record = #{
"Group Name" = ""
"Name" = ""
"Username" = ""
"mail" = ""
}
Foreach ($Group in $Groups) {
$Arrayofmembers = Get-ADGroupMember -identity $Group -recursive | select name,samaccountname
foreach ($Member in $Arrayofmembers) {
$Record."Group Name" = $Group
$Record."Name" = $Member.name
$Record."UserName" = $Member.samaccountname
$objRecord = New-Object PSObject -property $Record
$Table += $objrecord
}
}
$Table | export-csv "D:\Infolink.csv" -NoTypeInformation
Try this,
Import-Module ActiveDirectory
$groups = Get-ADGroup -Filter "name -like '*Infolink*'" -Properties ManagedBy
$table = foreach ($group in $groups) {
$Arrayofmembers = Get-ADGroupMember -Identity $group -Recursive
$ArrayofmembersUsers = $Arrayofmembers | Get-ADUser -Properties Mail
$ArrayofmembersUsers | Add-Member -Name GroupInfoLinkName -MemberType NoteProperty -Value $group.Name -Force
$ArrayofmembersUsers | Add-Member -Name GroupInfoLinkManageBy -MemberType NoteProperty -Value $group.ManagedBy -Force
$ArrayofmembersUsers
}
$table | Select-Object -Property GivenName, SurName, SamAccountName, Mail, GroupInfoLinkName, GroupInfoLinkManageBy | Export-Csv "D:\Infolink.csv" -NoTypeInformation
Some Pointers..
Use the Filter on Get-ADGroup else you're getting all groups in AD and then filtering.
PSObject are great but if your Object already has the majority of the properties you require then Add-Member is helpful to add 1 or 2 more.
Many cmdlets have a Properties parameter, you'll see I've used this to include properties that were not included by default. Unfortunately Get-ADGroupMember is not one of those cmdlets so piping to Get-ADUser helps provide a workaround.

Powershell to CSV compare

Hello I'm trying to use some code I found on here to compare a CSV with Active Directory. I have a csv file with a list of users. I want to check this file and see if anything in the "Email" column from the spreadsheet matches an email address from AD. If it does, I want to list that email address and include the Canonical Name from AD so I can easily see what OU the user account is in.
This is what I'm working with:
$path = "C:\Scripts\Import.csv"
$outpath = "C:\Scripts\Export.csv"
$csv = Import-Csv $path
Import-Module ActiveDirectory
foreach ($line in $csv)
{
$User = Get-ADUser -LDAPFilter "(&(objectclass=user)(mail=$($line.Email)))" -Properties CanonicalName
If ($User -ne $Null) {"User does exist in OU" + $line.Email + $User.CanonicalName}
Else {"User not found in AD OU - " + $line.Email}
}
I've been able to modify this to suit my needs but I'm having some trouble piping the results out to a CSV file. Running the script as it's shown above outputs what I want to the screen but I'd like to have it in a CSV format. If I do something like:
$Results = foreach ($line in $csv)
and then use
$Results | export-CSV $outpath -NotypeInformation
I get the csv created but it just includes a the string value, header for Length and then a numeric value for each line. I can use Out-File to send the results to a txt file, which includes the same results that were displayed on the screen, but I'd really like this to be a csv, not txt file. I believe I need to reference the properties of the csv file and AD in order to build these into my export file but I'm having trouble doing that as I'm not sure how to build in the status of whether the user was found or not.
Any assistance would be appreciated.
UPDATE - Final code
This is the final code I went with. This compares the users in the csv with AD users in the parent and child domain. It uses the email address field to match the users. It grabs the Canonical Name so I can see the OU the user is in and if the user is not found, it reports that in the Canonical Name field.
$path = "$env:userprofile\Desktop\InFile.csv"
$outpath = "$env:userprofile\Desktop\OutFile.csv"
# Importing CSV file
Import-Module ActiveDirectory
$Users = Import-Csv $path |
ForEach-Object {
Write-Progress -Activity "Comparing Imported File to Active Directory" -Status "Processing $($_.Email)"
# Comparing CSV file to Domain.com users
If (
$Value1 = (Get-ADUser -LDAPFilter "(&(objectclass=user)(mail=$($_.Email)))" -server Domain.com -Properties CanonicalName).CanonicalName)
{$_ | Add-Member -MemberType NoteProperty -Name CanonicalName -Value $value1 -PassThru}
# Comparing CSV file to child.Domain.com users
ElseIF (
$Value2 = (Get-ADUser -LDAPFilter "(&(objectclass=user)(mail=$($_.Email)))" -server child.Domain.com-Properties CanonicalName).CanonicalName)
{$_ | Add-Member -MemberType NoteProperty -Name CanonicalName -Value $value2 -PassThru}
# Writing output for users not found in either domain
Else {$_ | Add-Member -MemberType NoteProperty -Name CanonicalName -Value "Email Address not found in Active Directory" -PassThru}
#Exporting to CSV file
New-Object -TypeName pscustomobject -Property #{
Email = $_.Email
CanonicalName = $_.CanonicalName
LastName = $_."Last Name"
FirstName = $_."First Name"
}
} | Select-Object LastName, Firstname, Email, CanonicalName | Sort-Object CanonicalName | Export-CSV $outpath -NoTypeInformation
I'm not sure what resulting CSV should look like, so this code just adds CannonicalName using Calculated Properties to Import.Csv and saves it as Export.Csv.
$path = "C:\Scripts\Import.csv"
$outpath = "C:\Scripts\Export.csv"
Import-Module ActiveDirectory
Import-Csv -Path $path |
Select-Object -Property *, #{
n = 'CanonicalName'
e = {(Get-ADUser -LDAPFilter "(&(objectclass=user)(mail=$($_.Email)))" -Properties CanonicalName).CanonicalName}
} | Export-Csv -Path $outpath -NoTypeInformation
Update
This version will create a new CSV file with 3 columns: UserExistInOu, Email and CanonicalName if any:
Import-Csv -Path $path | ForEach-Object {
$UserExistInOu = $false
if($CanonicalName = (Get-ADUser -LDAPFilter "(&(objectclass=user)(mail=$($_.Email)))" -Properties CanonicalName).CanonicalName)
{
$UserExistInOu = $true
}
New-Object -TypeName pscustomobject -Property #{
UserExistInOu = $UserExistInOu
Email = $_.Email
CanonicalName = $CanonicalName
}
} | Export-Csv -Path $outpath -NoTypeInformation