Thumbnail: jekyll

PowerShell Streams

by on under PowerShell
3 minute read

I’ve put together the information below as a guide for some PowerShell Stream concepts that I’ve found are not well understood by most engineers. Streams are a fantastic structure built by the PowerShell team, but have not been well communicated.

Basics

basic

Most computing systems are built around only three standard streams: stdin (stardard in), stdout (standard out), and stderr (standard error). PowerShell is build with 6 standard output streams (as shown below). Note, as of this writing, the Progress Stream is under development.

When the cmdlet runs, some of the streams are enabled by default (a value of “Continue”) and some are not (a value of “SilentlyContinue”). As an example, the Success/Output, Error stream, and Warning streams are enabled by default and the Verbose and Debug streams are not.

So running a command like Write-Verbose -Message 'Hello World!' results in no operation. These streams can be enabled by using the Cmdlet’s common parameters. For example, Write-Verbose -Message 'Hello World!' -Verbose will result in VERBOSE: Hello World! being displayed on the commandline. The -Verbose flag tells the cmdlet to enable the verbose stream with this operation. Similarly in a script, you can use a Preference Variable like $VerbosePreference = 'Continue'. This will result in the entire script enabling the verbose stream. So the same command of Write-Verbose -Message 'Hello World' will result in VERBOSE: Hello World! being displayed on the commandline.

Table of output Streams

pipeline

Note that Write-Host has been refactored starting in PowerShell 5.0 to be a wrapper around the Write-Information cmdlet.

How streams work in PowerShell pipelines

pipeline

When running a cmdlet and piping the output to another cmdlet, only the Success/Output stream is passed from the first cmdlet (Cmdlet A in the image) to the second cmdlet (Cmdlet B in the image). This is what the “Output” portion of the stream name signifies. As an example, running: Get-Process | Where-Object {$_.ProcessName -eq 'chrome'}

Will result in an output like the following where the Success/Output stream pushes an array of objects from the Get-Process cmdlet to the Where-Object cmdlet that uses the values to filter the object’s data. Note that the other streams are not passed in the pipeline.

example execution

Redirection operator deep dive

redirection

Since the Verbose stream is not passed through the pipeline, operations like the following do not get passed from the Write-Verbose to the Out-File and the “B.txt” file is created but is empty.

Write-Verbose -Message 'Hello World!' -Verbose | Out-File .\B.txt

The redirection operator 4>&1 looks cryptic, but it makes sense when you parse it. It means that the Verbose stream (4) is redirected to the Success/Output Stream (1). This action is shown graphically in the image above.

Write-Verbose -Message 'Hello World!' -Verbose 4>&1 | Out-File .\B.txt

The result is as shown below.

redirection1

Additionally, operations like the following do not work with the conventional > redirection symbol as this redirects only for the success/output stream. Using the redirection of 4> to a file tells PowerShell to push the Verbose stream to the file named “.\A.txt” in the example below.

redirection2

More information

PowerShell