Search code examples
powershellexpressionhashtable

Powershell Expressions in Hashtable


I've been recently getting more into powershell scripting. I'm figuring stuff out as I go, but I can't work this problem out.

Basically I know this code works:

Get-Mailbox -ResultSize Unlimited |
Select-Object ExternalDirectoryObjectId, DisplayName,PrimarySmtpAddress, Alias, UserPrincipalName, ArchiveStatus, ArchiveDatabase,FirstName, LastName, RecipientTypeDetails, `
@{Name="EmailAddresses";Expression={
    ($_.EmailAddresses | 
    Where-Object {$_ -clike "smtp:*"} | 
    ForEach-Object {$_ -replace "smtp:",""}) -join "," 
}} |
Export-Csv "C:\temp\export.csv" -NoTypeInformation -Encoding UTF8

Problem is that I want to run commands from several modules on all mailboxes, to produce a single CSV, so I'm doing this:

$mailboxes = get-mailbox -resultsize unlimited
$export = @()

foreach($mailbox in $mailboxes)
{
    $UPN = $mailbox.MicrosoftOnlineServicesID
    $mailboxstat = Get-MailboxStatistics $UPN
    $MSOL = get-msoluser -UserPrincipalName $UPN        


    $Properties = @{
        "Object ID" = $mailbox.ExchangeGUID
        "Display Name" = $mailbox.DisplayName
        "Alias" = $mailbox.Alias
        "Primary SMTP Address" = $mailbox.PrimarySMTPAddress
        "Mailbox Size" = $mailboxstat.TotalItemSize
        "First" = $MSOL.FirstName
        "Last" = $MSOL.LastName
        "RecipientTypeDetails" = $mailbox.RecipientTypeDetails
        "ArchiveStatus" = $mailbox.ArchiveStatus
        "ArchiveGUID" = $mailbox.ArchiveGUID
        "LitigationHold" = $mailbox.LitigationHold
        "Licenses"=$MSOL.Licenses
        "ProxyAddresses"= @{Name="EmailAddresses";Expression={($_.EmailAddresses | Where-Object {$_ -clike "smtp:*"}
    }
    write-host $UPN

    #$properties += $x500

    $export += New-Object psobject -property $properties 
    
}
write-host $export
$exportpath = saveAs
$export | 
    select-object "Object ID", "Display Name","Primary SMTP Address","ProxyAddresses","ArchiveStatus","ArchiveGUID",First,Last,LitigationHold, "Mailbox Size" | 
    Export-Csv -notypeinformation -path $exportpath

Which works apart from the proxy addresses. If I put the hash/expression code in the Export code, it won't produce the results for each mailbox. But no matter how else I code it, I can't get it to produce what I want.
I've tried creating a new object within the $properties hashtable, convert-string, pretty much eveyrthing I can think of or find on google.
Can someone assist on how I need to format this code for it to work how I need?

Thanks in advance


Solution

  • Your issue is you're defining a hashtable that you're treating like the Properties argument for Select-Object, but you're then sending that to New-Object, which works in a very different way / converts a hashtable to a PSObject, rather than selecting existing properties.

    $export += ([PSCustomObject]@{
        "Object ID" = $mailbox.ExchangeGUID
        "Display Name" = $mailbox.DisplayName
        "Alias" = $mailbox.Alias
        "Primary SMTP Address" = $mailbox.PrimarySMTPAddress
        "Mailbox Size" = $mailboxstat.TotalItemSize
        "First" = $MSOL.FirstName
        "Last" = $MSOL.LastName
        "RecipientTypeDetails" = $mailbox.RecipientTypeDetails
        "ArchiveStatus" = $mailbox.ArchiveStatus
        "ArchiveGUID" = $mailbox.ArchiveGUID
        "LitigationHold" = $mailbox.LitigationHold
        "Licenses"=$MSOL.Licenses
        "ProxyAddresses"= ($mailbox.EmailAddresses | Where-Object {$_ -clike "smtp:*"}) -join ','
    })
    

    i.e. instead of providing the code to convert a the current object in the pipeline to a property called EmailAddresses, then having that result assigned to a property called ProxyAddresses, just calculate and assign the value that you want ProxyAddresses to have directly.

    I also used [PSCustomObject] before the hashtable to convert the hashtable to a PSCustomObject and assign it directly to your array. If you prefer though, you could continue to hold the hashtable in a variable (e.g. $properties as it was previously called), then pass that as an arument to New-Object to be converted to a PSObject before being assigned to your array.