2014 Winter PowerShell Scripting Games Wrap Up #4

Dr Scripto

February 20th, 2014

Summary: Microsoft Scripting Guy, Ed Wilson, continues his Scripting Games 2014 wrap up with a discussion of error and verbose message streams.

Microsoft Scripting Guy, Ed Wilson, is here. Things are starting to settle down here in the scripting household. Windows PowerShell Saturday #007 was a rousing success in Charlotte, North Carolina. Valentine’s Day was cool and a special treat for the Scripting Wife and I, and the 2014 Winter Scripting Games have concluded. So what’s to do? Well, today I am sipping a nice cup of Charleston Breakfast tea. I added peppermint, spearmint, honey, fresh lemon, and a cinnamon stick to the mixture. It is quite refreshing. Charleston Breakfast tea is one of the teas that is grown at the Charleston Tea Plantation. It has a nice robust flavor when steeped for four minutes in 208 degree water.

Note This is the fourth in a series of blog posts in which I talk about things I noticed whilst grading submissions for the

2014 Winter Scripting Games. In case you missed the previous episodes:

In today’s post, I’ll talk about using the Write-Verbose and Write-Error streams in Windows PowerShell scripts.

Alternative output message streams

One of the things I saw while grading scripts for the 2014 Winter Scripting Games was people creating their own alternate message streams. For example, they might do something like the following:

If($verbose) {Write-Host "This is verbose output"}

ELSE {Write-Host "This is normal output"}

Although this sort of thing might actually work (at least to an extent), it is not optimal. In fact, it causes a lot of extra work. This is because Windows PowerShell already has several message streams including:

Normal output

Errors

Warnings

Verbose output

Debug messages

Whether these messages display anything is due to the configuration of one of the following Preference variables:

DebugPreference

ErrorActionPreference

VerbosePreference

WarningPreference

The neat thing is that I implement my script in the proper Windows PowerShell fashion, then I can capture these alternate message streams in a text file via the redirection operators introduced in Windows PowerShell 3.0. The following table lists the redirection operators.

Note The 2>, 2>>, and 2&1 operators existed in Windows PowerShell 1.0.

Operator Description Example > Sends output to the specified file Get-Process > Process.txt >> Appends the output to the contents of the specified file dir *.ps1 >> Scripts.txt 2> Sends errors to the specified file Get-Process none 2> Errors.txt 2>> Appends errors to the contents of the specified file Get-Process none 2>> Save-Errors.txt 2>&1 Sends errors (2) and success output (1) to the success output stream Get-Process none, Powershell 2>&1 3> Sends warnings to the specified file Write-Warning "Test!" 3> Warnings.txt 3>> Appends warnings to the contents of the specified file Write-Warning "Test!" 3>> Save-Warnings.txt 3>&1 Sends warnings (3) and success output (1) to the success output stream Function Test-Warning {Get-Process PowerShell; Write-Warning "Test!" } Test-Warning 3>&1 4> Sends verbose output to the specified file Import-Module * -Verbose 4> Verbose.txt 4>> Appends verbose output to the contents of the specified file Import-Module * -Verbose 4>> Save-Verbose.txt 4>&1 Sends verbose output (4) and success output (1) to the success output stream Import-Module * -Verbose 4>&1 5> Sends debug messages to the specified file Write-Debug "Starting" 5> Debug.txt 5>> Appends debug messages to the contents of the specified file Write-Debug "Saving" 5>> Save-Debug.txt 5>&1 Sends debug messages (5) and success output (1) to the success output stream Function Test-Debug { Get-Process PowerShell; Write-Debug "PS" } Test-Debug 5>&1 *> Sends all output types to the specified file Function Test-Output { Get-Process PowerShell, none; Write-Warning "Test!"; Write-Verbose "Test Verbose"; Write-Debug "test debug"} ; Test-Output *> Test-Output.txt *>> Appends all output types to the contents of the specified file Test-Output *>> Test-Output.txt *>&1 Sends all output types (*) to the success output stream Test-Output *>&1

An example of how to use the alternate message streams is shown here:

$desktopPath = [System.Environment]::GetFolderPath("Desktop")

Function Out-VerboseStream

{

BEGIN { $oldVerbosePreference = $VerbosePreference }

PROCESS {

$VerbosePreference = "Continue"

Write-Verbose "This is verbose output"

"This is regular output" }

END {$VerbosePreference = $oldVerbosePreference }

}

The key features are to set the preference variable to “Continue” to permit it to output. As a best practice, you should set it back when you are finished. As shown in the following image, I first run the function, and the verbose stream and the regular stream appear in the output pane.

I now use the redirection operator to redirect the verbose stream output to a text file:

Now when I use the redirection operator to redirect the verbose stream, it goes in a text file.

The following table illustrates the different type of redirection characters that are used to represent the message streams.

Character Meaning * All output 1 Success output 2 Errors 3 Warning messages 4 Verbose output 5 Debug messages

That is all there is to using different output streams. 2014 Winter PowerShell Scripting Games Wrap-Up Week continues tomorrow when I will talk about using the Switch statement.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy