Nested foreach question

by penguinviw at 2013-04-04 12:37:24

My script collects the sub OUs under the KT OU, gets the mailbox info for each mailbox in each OU and outputs the mailbox info grouped by OU. What I can not seem to get it to do is put a line at the end of each group of OUs with the total space used by the mailboxes in that OU. It provides the total space used, but outputs as many lines as there is mailboxes in that OU. The math is right, it just produces duplicate lines of the totals. Here is my code:
Import-Module ActiveDirectory
if(!(Get-PSSnapin |
Where-Object {$.name -eq “Microsoft.Exchange.Management.PowerShell.E2010”})) {
ADD-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
}
# Variables
$ErrorActionPreference = “SilentlyContinue”
$WarningPreference = “SilentlyContinue”
$oulist = Get-OrganizationalUnit “KT” -SingleNodeOnly
# End Variables
ForEach ($Ounames in $Oulist) {
Write-Host “------“n $Ounames.Name n”------”
ForEach ($Mailbox in (Get-Mailbox -ResultSize Unlimited -OrganizationalUnit $Ounames.Name)){
Get-mailboxstatistics $Mailbox | Select @{label=“User”;expression={$
.DisplayName}},
@{name=“PrimarySMTPAddress”;expression={$mailbox.PrimarySMTPAddress}},
@{label=“TotalSizeMB”;expression={$.TotalItemSize.Value.ToMB()}},
@{label=“Items”;expression={$
.ItemCount}},
@{label=“Storage Limit”;expression={$.StorageLimitStatus}},
ServerName, Database
}
$CalculateOuSize = (Get-Mailbox -OrganizationalUnit $Ounames.Name | Get-mailboxstatistics | Measure-Object -Property ‘TotalItemSize’-Sum).Sum
[int]$TotalOuSize = $CalculateOuSize/1048576
Get-Mailbox -OrganizationalUnit $Ounames.Name | Get-mailboxstatistics | Select @{label=“Total OU MailBox Size”;expression={$TotalOuSize}}
Write-Host “-------------------------------------------------”
Write-Host n n
}

Thanks.
by penguinviw at 2013-04-04 12:38:53
Sorry, browser freaked out and double posted.
by mjolinor at 2013-04-04 14:20:44
Some observations:
Of those To* methods on the ByteQuantifiedSize object types being used for the mailbox sizes, only ToBytes produces an int result. The others are string. (You can’t sum strings).
Measure object needs an object collection to operate against.
You’re doing a lot of unnecessasry work going after those mailbox statistics twice.
A little white space can go a long way to toward making a script easier to read (and it’s free).

See if this makes sense:

Import-Module ActiveDirectory
if(!(Get-PSSnapin |
Where-Object {$
.name -eq “Microsoft.Exchange.Management.PowerShell.E2010”})) {
ADD-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
}
# Variables
$ErrorActionPreference = “SilentlyContinue”
$WarningPreference = “SilentlyContinue”

$oulist = Get-OrganizationalUnit “KT” -SingleNodeOnly
# End Variables


ForEach ($ounames in $oulist)
{
Write-Host “------“n $Ounames.Name n”------”

$MBXStats =
ForEach ($Mailbox in (Get-Mailbox -ResultSize Unlimited -OrganizationalUnit $Ounames.Name))
{
Get-mailboxstatistics $Mailbox | Select @{
label=“User”
expression={$.DisplayName}
},

@{
name=“PrimarySMTPAddress”
expression={$mailbox.PrimarySMTPAddress}
},

@{
label=“TotalSizeMB”
expression={$
.TotalItemSize.Value.ToMB()}
},

@{
label=“Items”
expression={$.ItemCount}
},

@{
label=“Storage Limit”
expression={$
.StorageLimitStatus}
},

@{
label=“TotalItemSizeBytes”
expression = {$_.TotalItemSize.Value.ToBytes()}
},

ServerName,
Database
}

$CalculateOuSize = ($MbxStats | Measure-Object -Property ‘TotalItemSizeBytes’ -Sum).Sum
[int]$TotalOuSize = $CalculateOuSize/1048576

$MBXStats | select -ExcludeProperty TotalItemSizeBytes
Write-host (’-’*50)
‘Total OU size is {0} MB’ -f $TotalOuSize
Write-host (’=’*50)
Write-host ("`n"*2)
}