Search code examples
powershellcastingpsobject

Weird Object[] casting from PSObject through a function call


I'm currently coding a function able to cast an ADO (EML attachments from Email) into a PSObject. A stub of the code looks like this:

function Get-OriginalMailAttributes([__ComObject]$email){
    #.DESCRIPTION Downloads in Temp the attachment and open it.
    # Returns PSObjectwith values.

    #STEP 1: Download EML
    $TEMPFILE = "..."

    if($email.Attachments.Count){
        $attachment=$email.Attachments|?{$_.Filename.endsWith(".eml")} | select -First 1
        $fileName = $TEMPFILE + $(New-Guid | select -exp Guid) + ".eml"
        $attachment.SaveAsFile($fileName)

        #STEP2 : Retrieve EML Objects
        $adoDbStream = New-Object -ComObject ADODB.Stream
        $adoDbStream.Open()
        $adoDbStream.LoadFromFile($fileName)
        $cdoMessage = New-Object -ComObject CDO.Message
        $cdoMessage.DataSource.OpenObject($adoDbStream, "_Stream")

        #STEP 3: Bind values
        $attributes = New-Object PSObject -Property @{
            From = [string]($cdoMessage.Fields.Item("urn:schemas:mailheader:from").Value.toString())
        }

        #STEP 4: Cleanup
        [System.Runtime.InteropServices.Marshal]::ReleaseComObject($cdoMessage)
        [System.Runtime.InteropServices.Marshal]::ReleaseComObject($adoDbStream)
        Remove-Item $fileName

        return $attributes
        # Note that the debugger acknowledge the fact that $attributes is PSObject.
    }
}

I'm then calling the function at some point:

$sender_raw = Get-OriginalMailAttributes $email
$sender_raw.getType()

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

$sender_raw
0
0

From
----
"Bob" <[email protected]>
$sender_raw.From # Crashes.

Where does this behavior come from?


Solution

  • Typically when you have "extra" values in the output from a function it's because you're calling methods that have return values and not dealing with those values.

    .Add() methods are notorious for outputting the index of the item that was added.

    To avoid this problem, you have a few options:

    • Cast to void: [void]$collection.Add($item)
    • Assign to $null: $null=$collection.Add($item)
    • Pipe to out-null: $collection.Add($item) | out-null

    I don't see any obvious methods in your code, but adding Write-output 'Before Step 1' etc. throughout the code should make it clear where the offending statements are.