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@email.org"){
if ($item.body -match $RE){
[PSCustomObject]@{
AccName = $Matches.AccName
}
}
}
}
$Data
$Data | Export-CSv '.\data.csv' -NoTypeInformation
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:
$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).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
.