Search code examples
powershelldebuggingwrite-host

Trying to test code, keep getting "System.____comobject" instead of variable value


I'm trying to write a small powershell script that does a few things

1) Parses Inbox items in my outlook 2) Searches for a RegEx string 3) Dumps the line that matches the RegEx string into a CSV

I can't get #3 to work. It definitely runs for about 10 minutes, but the resulting csv is empty.

Here's a snippet of what I want it to look for:

Account Name: Jbond

I tried just slapping a "Write-Host $variable" in various parts to see what was happening, but all I get is "System.____comobject". I can't find a solution online to just convert this into plain text.

Add-Type -Assembly "Microsoft.Office.Interop.Outlook"
$Outlook = New-Object -ComObject Outlook.Application
$namespace = $Outlook.GetNameSpace("MAPI")
$inbox = $namespace.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox)                                                                                  
$RE = [RegEx]'(?sm)Account Name\s*:\s*(?<AccName>.*?)$.*'

$Data = ForEach ($item in $inbox.items){
    $resultText = $item.item.Value
    Write-Host $resultText
    if ($item.from -like "[email protected]"){
        if ($item.body -match $RE){
            [PSCustomObject]@{
                AccName = $Matches.AccName
            }
        }
    }
}
$Data 
$Data | Export-CSv '.\data.csv' -NoTypeInformation

Solution

  • tl;dr:

    Use:

    $variable | Out-Host # or: Out-Host InputObject $variable
    

    rather than

    Write-Host $variable
    

    to get meaningful output formatting.

    Background information and debugging tips below.


    Try a combination of the following approaches:

    Use interactive debugging:

    • Use GUI editor Visual Studio Code with the PowerShell extension to place breakpoints in your code and inspect variable values interactively. (In Windows PowerShell you can also use the ISE, but it is obsolescent.)

    • Less conveniently, use the *-PSBreakpoint cmdlets to manage breakpoints that are hit when you run your script in a console (terminal) window. A simple alternative is to add Wait-Debugger statements to your script, which, when hit, break unconditionally.


    Produce helpful debugging output:

    Generally, use Write-Debug rather than Write-Host, which has two advantages:

    • You can leave Write-Debug calls in your code for on-demand debugging at any time:

      • They are silent by default, and only produce output on an opt-in basis, via (temporarily) setting $DebugPreference = 'Continue' beforehand or passing the -Debug switch (if your script / function is an advanced one, though note that in Windows PowerShell this will present a prompt whenever a Write-Debug call is hit).
      • You do, however, pay a performance penalty for leaving Write-Debug calls in your code.
    • Debug output is clearly marked as such, colored and prefixed with DEBUG:.

    The problem you experienced with Write-Host is that all Write-* cmdlets perform simple .ToString() stringification of their arguments, which often results in unhelpful representations, such as System.____comobject in your case.

    To get the same rich output formatting you would get in the console, use the following technique, which uses Out-String as a helper command:

    $variable | Out-String | Write-Debug
    

    If you want to control the view (list vs. table vs. wide vs. custom) explicitly, insert a Format-* call; e.g.:

    $variable | Format-List | Out-String | Write-Debug
    

    It is generally only the standard Out-* cmdlets that use PowerShell's output formatting system.


    A quick-and-dirty alternative to Write-Debug is to use Out-Host rather than Write-Host - e.g., for quick insertion of debugging commands that you'll remove later; Out-Host itself performs the usual output formatting, which simplifies matters:

    # Default for-display formatting
    $variable | Out-Host  # or: Out-Host -InputObject $variable
    
    # Explicit formatting
    $variable | Format-List | Out-Host
    

    Caveat: Aside from formatting, another important difference between Write-Host and Out-Host is that in PSv5+ only Write-Host writes to the host via the information stream (stream number 6), whereas Out-Host truly writes directly to the host, which means that its output cannot be captured with redirections such as 6> or *> - see about_Redirection.