0

I've function DoWork which creates an object and keeps it in $AllMailboxes variable. Then within that function I execute another function ProcessEmail which is supposed to take $Mailbox out of $AllMailboxes and variable by ref, add couple of fields to it and either update $AllMailboxes or create new $collection which then holds all $Mailbox with updated fields

$collection = @()

function DoWork() { 
    Get-User -ResultSize Unlimited | Where { $_.RecipientType -eq 'UserMailbox' } | ForEach { $Users = @{} } { $Users[$_.SamAccountName] = $_ }
    $AllMailboxes = Get-Mailbox -ResultSize Unlimited | Where { $_.RecipientTypeDetails -eq "UserMailbox" } | ForEach {
    $PrimarySmtpDomain = $_.PrimarySmtpAddress.split("@")

    New-Object psobject | 
        Add-Member -PassThru NoteProperty Alias $_.Alias | 
        Add-Member -PassThru NoteProperty Name $_.Name |        
        Add-Member -PassThru NoteProperty DisplayName $_.DisplayName 
        Add-Member -PassThru NoteProperty .... other values
     foreach ($mailbox in $allmailboxes) {
         $FullEmail = "somestring"
         ProcessEmail ([ref] $Mailbox) ($FullEmail)
     }
     $collection | ft # doesn't display anything


}

function ProcessEmail ([ref] $Mailbox, $FullEmail) {
    $RequireAdd = $true
    $addresses = $Mailbox.EmailAddresses
    foreach ($address in $addresses) {
        if ($address -imatch "sip:") { continue }
        if ($address -ireplace("smtp:","") -ieq $FullEmail) {
            $requireAdd = $false
            break
    }

    $Mailbox | Add-Member -MemberType NoteProperty -Name NewEmailToAdd -Value $FullEmail 
    $Mailbox | Add-Member -MemberType NoteProperty -Name NewEmailRequiresAdding -Value $RequireAdd  
    $Mailbox.NewEmailToAdd # displays correctly
    $Mailbox.NewEmailRequiresAdding #display correctly
    $collection += $Mailbox
}

I've tried multiple approces with ref, without ref, creating separate variables but I can't for some reason make it to display anything in $collection or in other means outsied of ProcessEmail function. I'm sure I'm missing something.

MadBoy
  • 10,824
  • 24
  • 95
  • 156

3 Answers3

1

Seems like you are missing scope. Change it to at least script scope, like this:

$script:collection = @()
$script:collection += $Mailbox
Kirill Pashkov
  • 3,118
  • 1
  • 15
  • 20
  • It seems to act better but it only shows 2 fields I added in process email and doesn't show all others that were part of $Mailbox before? Also maybe I should pass $collection by ref as well ? What is best approach to this? – MadBoy Aug 02 '16 at 08:06
  • It seems new fields were added but all Mailbox fields are stored inside value now.. @{Alias=weronika.palowska; Name=Weronika Palowska;. So the $Mailbox has 3 fields, 2 new ones and all the other fields within Value.. what would be proper way to expand fields to add 2 more fields – MadBoy Aug 02 '16 at 08:08
  • $Mailbox | Add-Member -MemberType NoteProperty -Name NewEmailToAdd -Value $FullEmail - this doesn't seem to add another field – MadBoy Aug 02 '16 at 08:09
  • You could try pass ref collection as well. – Kirill Pashkov Aug 02 '16 at 08:12
1

You're making it more complex by using PSReference (which would need you to access the value property). You have no need to here so far.

There's also little need to use that global / script variable except perhaps as an assignment from DoWork as shown in this mock up.

function DoWork {
    foreach ($i in (1..100)) {
        $psObject = [PSCustomObject]@{
            Property1 = 1
            Property2 = 2
        }

        ProcessEmail -Mailbox $psObject -FullEmail $FullEmail

        $psObject
    }
}

function ProcessEmail {
    param(
        $Mailbox,
    )

    $Mailbox | Add-Member NewProperty1 "one"
    $Mailbox | Add-Member NewProperty2 "two"
}

$collection = DoWork

Chris

Chris Dent
  • 3,910
  • 15
  • 15
  • Yes, i thought it's over complex. I've revised my code to use simpler approach :-) – MadBoy Aug 02 '16 at 08:46
  • But for the sake of learning I wanted to know hot to use ref properly where main object is updated and I can then assign it as I want to. – MadBoy Aug 02 '16 at 08:50
  • PSObject is a bad example in that it has a degree of persistence, so this example adjusts the value in a variable containing an integer by way of a PSReference. `code`function one { [Int]$one = 1; two ([Ref]$one); $one }; function two ([Ref]$two) { $two.Value = 2 }; one – Chris Dent Aug 02 '16 at 09:37
  • Fixing mark down. `function one { [Int]$one = 1; two ([Ref]$one); $one }; function two ([Ref]$two) { $two.Value = 2 }; one` – Chris Dent Aug 02 '16 at 09:44
0

I've actually decided to go

function ProcessEmail ($Mailbox, $FullEmail) {
    $RequireAdd = $true
    $addresses = $Mailbox.EmailAddresses
    foreach ($address in $addresses) {
        if ($address -imatch "sip:") { continue }
        if ($address -ireplace("smtp:","") -ieq $FullEmail) {
            $requireAdd = $false
            break
        }
    }
    $Mailbox | Add-Member -MemberType NoteProperty -Name NewEmailToAdd -Value $FullEmail 
    $Mailbox | Add-Member -MemberType NoteProperty -Name NewEmailRequiresAdding -Value $RequireAdd  
    return ,$mailbox
}    

And simply go by:

$Mailbox = ProcessEmail ($Mailbox) ($FullEmail)
$collection += $Mailbox

Seems to work just fine.

MadBoy
  • 10,824
  • 24
  • 95
  • 156