PowerShell: Add New Value to Array - arrays

Using PowerShell I retrieve information from multiple ActiveDirectory groups and output it to a single CSV file. To each row I want to add the name of the group, in addition to the information retrieved. How can I achieve this?
Desired Result:
"CN","Department","co","Company","Group"
"ABCDEF","Media","UK","Global Entertainment","XXX"
Current Result:
"CN","Department","co","Company"
"ABCDEF","Media","UK","Global Entertainment"
My PowerShell code:
#Roles to check membership for
$Roles= #(
'XXX'
'YYY'
)
$FolderName = "C:\"
$OutputAD = #()
foreach ($role in $Roles) {
$GroupMembers = Get-ADGroupMember -identity $role | select name
$GroupMembersArray = $GroupMembers | Foreach {"$($_.Name)"}
$GroupMembersArray | ForEach-Object {
$UserLookup = Get-ADUser -Filter "Name -eq '$_'" -Properties CN,Department,co,Company | Select-Object CN,Department,co,Company
$OutputAD += $UserLookup
}
}
$OutputAD | Export-Csv "$FolderName\Membership $(get-date -Format yyyy-MMM-dd-HH-mm-ss).csv" -NoTypeInformation

Found the solution. In Select-Object you can add a calculated property.
Example: Select-Object CN,Department,co,Company,#{n='Role';e={$role}}

Related

Array causing 'system.outofmemoryexception'

I am running the below script and it is causing exception of type 'system.outofmemoryexception' was thrown
I believe that it is due to the #Results array growing past the 2gb allocated to windows shell. Is there possibly a way to iterate through the results, or am I stuck with allocating more memory (which could ultimately be a lot...)?
$Path = "path to output"
### Get all PF
$publicFolders = Get-PublicFolder "Public Folder Name" -Recurse -resultsize unlimited | Select-Object *
### Array to contain results
$results = #()
###Begin looping through each PF and grab each user/group with AccessRights to that folder
$final = ForEach($pf in $publicFolders){
$perms = Get-PublicFolderClientPermission -Identity $pf.Identity | Where-Object {$_.User -notmatch "Default|Anonymous|S-X-X-XX"}
Foreach($perm in $perms){
$temp = [PSCustomObject]#{
MailFolderName = $pf.Identity
UserWithPerms = $perm.User
AccessRights = $perm | Select-Object -ExpandProperty AccessRights
}
$results += $temp
}
}
$final | Export-Csv $path -NoTypeInformation
Am I barking up the wrong tree?
Thanks in advance.
Use the ForEach-Object cmdlet instead of a foreach(){} loop statement for the outer loop - this way you can start piping the output to Export-Csv immediately instead of buffering it in an array:
$publicFolders |ForEach-Object {
$pf = $_
$perms = Get-PublicFolderClientPermission -Identity $pf.Identity | Where-Object {$_.User -notmatch "Default|Anonymous|S-X-X-XX"}
Foreach($perm in $perms){
[PSCustomObject]#{
MailFolderName = $pf.Identity
UserWithPerms = $perm.User
AccessRights = $perm | Select-Object -ExpandProperty AccessRights
}
}
} | Export-Csv $path -NoTypeInformation
Alternatively, flush the partial set of results to file after enumerating the permissions for each folder:
ForEach($pf in $publicFolders){
$perms = Get-PublicFolderClientPermission -Identity $pf.Identity | Where-Object {$_.User -notmatch "Default|Anonymous|S-X-X-XX"}
$results = Foreach($perm in $perms){
[PSCustomObject]#{
MailFolderName = $pf.Identity
UserWithPerms = $perm.User
AccessRights = $perm | Select-Object -ExpandProperty AccessRights
}
}
# flush the buffer before moving to the next set of permissions
$results |Export-Csv $path -NoTypeInformation -Append
}

Export-Csv Cannot bind argument to parameter 'InputObject' because it is null

I am trying to fetch the AD group members information through power shell. But I am getting the messages as
Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null.
Import-Module ActiveDirectory
$Path = Get-Location
$GroupName = Read-Host "Type the Group Name to check the members in it`t "
foreach ($group in $GroupName) {
$users = #{}
Get-ADUser -Filter '*' -Property Name, DisplayName | ForEach-Object {
$users[$_.DistinguishedName] = $_
}
$MemberCount = (Get-ADGroup $group -Properties Member | Select-Object -Expand Member).Count
Write-Host "`t Total Number of Users/Groups added on this Group : $MemberCount" -BackgroundColor DarkCyan
$Info = Get-ADGroup $group -Properties Member |
Select-Object -Expand Member |
ForEach-Object { $users[$_] }
$Info | Export-Csv -NoTypeInformation -Append -Force $Path\new.csv
The error means that $Info contains empty/null values. The most likely reason for their presence is that the group has members that aren't returned by Get-ADUser.
You can avoid the issue by checking for the presence of the key in the $users hashtable:
$Info = Get-ADGroup $group -Properties Member |
Select-Object -Expand Member |
ForEach-Object { if ($users.ContainsKey($_) {$users[$_]} }
If you want to further investigate the missing distinguished names you could collect them like this:
$missing = Get-ADGroup $group -Properties Member |
Select-Object -Expand Member |
ForEach-Object { if (-not $users.ContainsKey($_) {$_} }

Can I combine these two arrays

I have some simple Exchange Powershell I have written. I would like to list the UPN, Displayname, Item Count, and Item Size into a single CSV. However I have only been able to successfully push the data to two arrays and then manually combine them. Here is my code.
$MailBoxs = Get-Mailbox * | Select UserPrincipalName -ExpandProperty UserPrincipalName | Sort-Object UserPrincipalName
$Mailboxs2 = $MailBoxs.Where({ $_ -ne $null })
ForEach($MailBox2 in $MailBoxs2) { Get-MailboxStatistics $Mailbox2 | Sort-Object TotalItemSize –Descending | Select #{label=”User”;expression={$_.DisplayName}},#{label=”Total Size (MB)”;expression={$_.TotalItemSize.Value.ToMB()}},#{label=”Items”;expression={$_.ItemCount}} | Export-CSV "C:\T2\MailBoxSize.csv" -Append -NoTypeInformation }
ForEach($MailBox2 in $MailBoxs2) { $Mailbox2 | Export-CSV "C:\T2\MailBoxSize2.csv" -Append -NoTypeInformation }
Basically the second CSV gives me two fields for some reason the SMTP address and some random Length field, It also gives me a leading whitespace. If anyone has any ideas on how to clean this up I would love to hear them. Thanks for your time.
The multiple select statements were unnecessary. Here's a bit simplified way:
$mailboxes = #(Get-Mailbox *).
Where({$_.UserPrincipalName}) |
Sort-Object -Property UserPrincipalName
foreach ($box in $mailboxes) {
Get-MailboxStatistics $box.UserPrincipalName |
Sort-Object -Property TotalItemSize -Descending |
Select-Object -Property #(
#{L='UPN';E={$box.UserPrincipalName}}
#{L='User';E={$_.DisplayName}}
#{L='Total Size (MB)';E={$_.TotalItemSize.Value.ToMB()}}
#{L='Items';E={$_.ItemCount}}
) |
Export-Csv -Path 'C:\T2\MailBoxSize.csv' -NoTypeInformation -Append
}

How do I add a user to multiple groups

I want to specify a source user and capture the list of the groups that user belongs to. I want to then specify a second user and have the original captured groups added to the new users account.
If user1 is a member of GroupA, GroupB, GroupC I want the script to capture that and add it to user3 when I type his name.
Import-Module ActiveDirectory
$SourceUser = Read-Host -Prompt 'Enter the username of the user whos groups you would like to copy'
$DestUser = Read-Host -Prompt "Enter the username of the user who will get: $SourceUser groups"
$SourceGroups = Get-ADUser $SourceUser -Property MemberOf | % {
$_.MemberOf | Get-ADGroup | select Name | sort name
}
"List of groups for user $DestUser BEFORE script: "
Get-ADUser $DestUser -Property MemberOf | % {
$_.MemberOf | Get-ADGroup | select Name | sort name
}
# ***Where my problem is***
#Add-ADGroupMember $SourceGroups –Member $DestUser
"List of groups for user $DestUser AFTER script: "
Get-ADUser -Identity $DestUser -Property MemberOf | % {
$_.MemberOf | Get-ADGroup | select Name | sort name
}
When in doubt, read the documentation.
Syntax
Add-ADGroupMember [-Identity] <ADGroup> [-Members] <ADPrincipal[]> ...
The -Identity parameter (the first argument) takes a single group identity, not a list of identities. To add a user to a list of groups you need a loop:
$SourceGroups | ForEach-Object { Add-ADGroupMember $_ –Member $DestUser }
Here is the corrected code that now works.
$T2FolderExists = Test-Path "C:\T2\"
$LogsFolderExists = Test-Path "C:\T2\Logs\"
IF ($T2FolderExists -eq $False)
{
New-Item C:\T2\ -type directory
IF ($LogsFolderExists -eq $False)
{
New-Item C:\T2\Logs\ -type directory
}
ELSE
{
}
"`n"
Start-Transcript -Path C:\T2\Logs\CopyMembershipFromADAccount.txt -Append
"`n"
}
ELSE
{
"`n"
Start-Transcript -Path C:\T2\Logs\CopyMembershipFromADAccount.txt -Append
"`n"
}
<#*****Session Paramaters*****>
Set-ExecutionPolicy Unrestricted -force
Import-Module ActiveDirectory
Clear-Host
Write-Host "Enter the username of the user whos groups you would like to copy" -foregroundcolor Green -backgroundcolor Black
$SourceUser = Read-Host
"`n"
Write-Host "Enter the username of the user who will get: $SourceUser groups" -foregroundcolor Green -backgroundcolor Black
$DestUser = Read-Host
"`n"
$SourceGroups = Get-ADUser $SourceUser -Property MemberOf | ForEach-Object {
$_.MemberOf | Get-ADGroup | select Name -ExpandProperty Name | sort name
}
"`n`n"
Write-Host "List of groups for user $SourceUser BEFORE script: "
Get-ADUser $SourceUser -Property MemberOf | ForEach-Object {
$_.MemberOf | Get-ADGroup | select Name -ExpandProperty Name | sort name
}
"`n`n"
Write-Host "List of groups for user $DestUser BEFORE script: "
Get-ADUser $DestUser -Property MemberOf | ForEach-Object {
$_.MemberOf | Get-ADGroup | select Name -ExpandProperty Name | sort name
}
"`n`n"
ForEach ($Group in $SourceGroups)
{
Add-ADGroupMember $Group –Member $DestUser
Write-Host "Adding $Group to $DestUser 's Account" -foregroundcolor Cyan -backgroundcolor Black
}
"`n`n"
Write-Host "List of groups for user $SourceUser BEFORE script: "
Get-ADUser $SourceUser -Property MemberOf | ForEach-Object {
$_.MemberOf | Get-ADGroup | select Name -ExpandProperty Name | sort name
}
"`n`n"
Write-Host "List of groups for user $DestUser AFTER script: "
Get-ADUser $DestUser -Property MemberOf | ForEach-Object {
$_.MemberOf | Get-ADGroup | select Name -ExpandProperty Name | sort name
}
"`n"
Stop-Transcript
Exit
This is what I did:
Import-Module ActiveDirectory
Import-CSV "data.csv" -Delimiter ";" |
ForEach {`
$_.Group1,$_.Group2,$_.Group3,$_.Group4,$_.Group5,$_.Group6 |
Add-ADGroupMember `
-Members $_.Alias`
}
You can have more groups in the script without using them.
And in the "data.csv", you put this (for example):
Alias;Group1;Group2;Group3;Group4
l.salvador;Spanish;Republic;Central;WWW
Although I had an error with "Identity" could not be checked, it worked.

Call a Group Object by Name in ForEach Loop

I've imported a CSV file into an array and grouped it by email address. I'd like to be able to call the group by name in another ForEach loop so that I can send an email to each email address with a table of the $ServerID(s) and $DateTime(s) associated with them. Was Group-Object the best way to start this?
In the CSV file, one email address can be associated with many servers, but one server is only associated with one email address. The values in the file will be updated constantly - thus the need for dynamic variables for almost all objects.
$csv = import-csv "C:Example.csv"
$array = #()
ForEach ($server in $csv) {
$object = New-Object PSObject -Property #{"Email"= $server.Email; "ServerID" = $server.ServerID; "DateTime" = $server.DateTime}
$array += $object}
$array | Group-Object Email
Count Name Group
2 A#gmail.com {#{PG_Email=A#gmail.com; ServerID=333; Lease_End=10/10/15}, #{PG_Email=A#gmail.com; ServerID=111; Lease_End=12/12/15}}
1 B#gmail.com {#{PG_Email=B#gmail.com; ServerID=222; Lease_End=09/09/15}}
Yes, you should use Group-Object. I'm not sure what you mean with "call the group by name". If you want to select a group based by the name you would have to save the result from Group-Object and search for your group like:
$groups = $array | Group-Object Email
$selectedmail = "B#gmail.com"
$groups | Where-Object { $_.Name -eq $selectedmail }
Or you could save the groups in a hashtable:
#Create hashtable
$ht = #{}
#Fill hashtable with groups (email as key/ID)
$array | Group-Object Email | ForEach-Object { $ht[$_.Name] = $_.Group }
$selectedmail = "B#gmail.com"
#Get objects for selected mail
$ht[$selectedmail]
If you are going to mail everyone, I would simplify this to:
Import-Csv "C:\Example.csv" |
Group-Object Email |
ForEach-Object {
$to = $_.Name
#Get table of ServerID + Lease_End as string to send as mailbody
$mailbody = $_.Group | Format-Table -Property ServerID, Lease_End -AutoSize | Out-String
#You could also create a HTML-table with:
$htmlbody = $_.Group | Select-Object -Property ServerID, Lease_End | ConvertTo-HTML -Property Name, Length
#Send mail
#Send-MailMessage -To $to -Subject "Lease-status" -Body $mailbody -From "mysupersecret#mail.com"
}

Resources