Author Posts

April 11, 2017 at 1:45 pm

A little confused,

so i want to retreive all mailboxes and output them to an array which is working fine code below


$MBDatabases = Get-MailboxDatabase | where {$_.name -like "*EU*"} | select name


$outarray = @()

foreach ($MBDatabase in $MBDatabases)
{
    $Users = Get-MailboxStatistics -Database $MBDatabase.name | where {$_.ObjectClass -eq “Mailbox”}
   
   

    foreach ($user in $users)

    {
        $properties = @{Name = $User.Displayname
                        MBSize = $User.TotalItemSize
                        ItemCount = $User.ItemCount
                        Database = $user.Database
                        Servername = $user.ServerName
                              

                        }

    $Obj = New-Object -TypeName psobject -Property $properties
$outarray  += $obj 
                     }
   
}

$outarray | Out-GridView

now i also want to include the 'title' & 'samAccountname' attribute in the object, to get the details im using


$user2 = $user | select -ExpandProperty displayname

    $adusers = get-aduser -filter {displayname -eq $user2} -Properties title | select title, samaccountname

i want to combine the two commands so i output one array of objects


$properties = @{Name = $User.Displayname
                        MBSize = $User.TotalItemSize
                        ItemCount = $User.ItemCount
                        Database = $user.Database
                        Servername = $user.ServerName
                        Title = $aduser.title
                        SamAccountName = $aduser.samaccountname
                              }

i know im going wrong somewhere but lost as to where ? last method i tried was below but seems to only give me the last result of each DB, HEEEELLLP!


$MBDatabases = Get-MailboxDatabase | where {$_.name -like "*EU*"} | select name


$outarray = @()

foreach ($MBDatabase in $MBDatabases)
{
    $Users = Get-MailboxStatistics -Database $MBDatabase.name | where {$_.ObjectClass -eq “Mailbox”}
   
 

    foreach ($user in $users)

    {

    $user2 = $user | select -ExpandProperty displayname

    $adusers = get-aduser -filter {displayname -eq $user2} -Properties title | select title, samaccountname
    foreach ($aduser in $Adusers)
    {
        
    
        $properties = @{Name = $User.Displayname
                        MBSize = $User.TotalItemSize
                        ItemCount = $User.ItemCount
                        Database = $user.Database
                        Servername = $user.ServerName
                        Title = $aduser.title
                        SamAccountName = $aduser.samaccountname
                              }

                              }
                        }

    $Obj = New-Object -TypeName psobject -Property $properties
$outarray  += $obj 
                     }
   


$outarray | Out-GridView

April 11, 2017 at 2:35 pm

for each MailBoxStatistic object you easily can get mailbox or user with

Get-Mailbox -Identity $user.LegacyDN
Get-User -Identity $user.LegacyDN

and do something like

# [...]
$Users = Get-MailboxStatistics -Database $MBDatabase.name | where {$_.ObjectClass -eq “Mailbox”}
foreach ($user in $users)
$mb = Get-MailBox $user.LegacyDN
$us = Get-User $user.LegacyDN
#Do not use "$obj =" here, let it flow thru pipeline
[PSCustomObject]@{
                        MBSize = $User.TotalItemSize
                        ItemCount = $User.ItemCount
                        Database = $user.Database
                        Servername = $user.ServerName
                        Title = $us.title
                        SamAccountName = $us.samaccountname
}

and please do not use accumulator like "$outarray += $obj"
you can

foreach ($MBDatabase in $MBDatabases)
{
# [...]
} | Out-GridView

April 11, 2017 at 7:45 pm

Much appreciated Max, will give this a shot first thing tomorrow

April 12, 2017 at 9:33 am

Hi Max gave this a shot today, but it reports the last line in wrong


$MBDatabases = Get-MailboxDatabase | where {$_.name -like "*EU*"} | select name




foreach ($MBDatabase in $MBDatabases)
{
    $Users = Get-MailboxStatistics -Database $MBDatabase.name | where {$_.ObjectClass -eq “Mailbox”}
   
   

    foreach ($user in $users)

    {

    $mb = Get-MailBox $user.LegacyDN
    $us = Get-User $user.LegacyDN
    
[PSCustomObject]@{
                        MBSize = $User.TotalItemSize
                        ItemCount = $User.ItemCount
                        Database = $user.Database
                        Servername = $user.ServerName
                        Title = $us.title
                        SamAccountName = $us.samaccountname
                              

                        }
                     }
   
}| Out-GridView -Wait

At H:\EAA\Powers Shell Commands\get all mb sizes.ps1:31 char:2
+ }| Out-GridView -Wait
+  ~
An empty pipe element is not allowed.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : EmptyPipeElement

April 12, 2017 at 10:42 am

sorry, I'm misinform you
this way works

$output = foreach ($MBDatabase in $MBDatabases)
{
# [...]
}
$output | Out-GridView

April 12, 2017 at 10:47 am

Thanks max, just another quick Q

out of interest whats the benefit of this over adding objects to an array ?

April 13, 2017 at 4:49 am

Hey Mark,
Both methods result in an array.

Example

$numlist = 1..10
$addarray = @()
$returnedarray = foreach ($num in $numlist) {
    $psobj = [pscustomobject]@{
        num = $num
    }
    $addarray += $psobj
    $psobj
}

In the above example we are using both methods. One to add the custom PS object to $addarray using +=, and the other to return the custom PS object so that it is included in $returnedarray as a return value.

With these two variables now populated with values, the same values, we can check out what they are using Get-Member

(Get-Member -InputObject $addarray).GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                      
-------- -------- ----                                     --------                                                                                                      
True     True     Object[]                                 System.Array
(Get-Member -InputObject $returnedarray).GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                      
-------- -------- ----                                     --------                                                                                                      
True     True     Object[]                                 System.Array

As you can see both BaseTypes are System.Array

The difference is that collecting the objects into an array as they are returned seems to be faster than adding them to an array using +=.

$numlist = 1..10000
$addarray = @()

Measure-Command {
    $returnedarray = foreach ($num in $numlist) {
        [pscustomobject]@{
            num = $num
        }
    }
} | Select-Object -ExpandProperty TotalSeconds

Measure-Command {
    foreach ($num in $numlist) {
        $addarray += [pscustomobject]@{
            num = $num
        }
    }
} | Select-Object -ExpandProperty TotalSeconds

0.141293
6.5053623

April 13, 2017 at 6:00 am

In addition to @Curtis explanation

"+=" also memory expensive

for array with 10000 elements after "$array += 1"
you have two arrays in memory: named $array with 10001 element and unnamed (old) with 10000 elements
it falls under GarbageCollection after that but still exists some time...

April 13, 2017 at 7:22 am

Thanks both, have a much better understanding now