Summary: Learn about the Windows PowerShell information stream in this guest post by June Blender.
Microsoft Scripting Guy, Ed Wilson, is here. Today we have another guest blog post by Honorary Scripting Guy, Windows PowerShell MVP, and Sapien technical evangelist, June Blender. Take it away June...
This post introduces the new information stream in Windows PowerShell 5.0. It explains the issue it tries to solve and its elegant solution.
In March 2014, I wrote a Hey, Scripting Guy! Blog post, Understanding Streams, Redirection, and Write-Host in PowerShell, which explained the output streams in Windows PowerShell.
The outlier in the stream world has always been the much-maligned Write-Host cmdlet. Windows PowerShell inventor, Jeffrey Snover stateded Write-Host Considered Harmful. Famously, in his 2012 Scripting Games commentary, Stop Using Write-Host!, Windows PowerShell MVP and first follower, Don Jones, proclaimed that Write-Host kills puppies. That’s a lot of high-powered condemnation for a cmdlet.
And, it’s all about to change. With the advent of the information stream in Windows PowerShell 5.0, Write-Host is being redeemed. Actually, it's being, well...mainstreamed.
Write-Host and streams
The root of the problem is that in Windows PowerShell versions 1.0 through 4.0, Write-Host output doesn’t go to a stream. It goes straight to the host program, such as the console, ISE, or PowerShell Studio. What happens then is determined by the host program, and it might vary.
Because Write-Host doesn't go to a stream, if you put Write-Host in a script, the end-user can't suppress it, can't save it, and can't redirect it.
- You can't suppress Write-Host output because there's no preference that silences it.
- You can’t save Write-Host output in a variable, because the assignment operator uses the output stream. The Write-Host output is written to the host program, but the variable is empty.
- You can't pass Write-Host output down the pipeline, because only the output stream goes down the pipeline.
- You can't redirect Write-Host output, because redirection sends output from one stream to another, and Write-Host isn't part of any stream.
Write-Host and stream pollution
Despite this very high-level condemnation, people kept using Write-Host, precisely because it doesn't go to a stream. Write-Host is eco-friendly, because it doesn't pollute the output stream.
The underlying principle is that every command should generate one type of output. For example, Get-Process returns Process objects, and Start-Job returns PSRemotingJob objects.
You never want a command like the following, which returns process objects and a string:
In its own sad way, Write-Host solves this problem. In this version, I replaced Write-Output with Write-Host. Now this function writes a process object and a string, but only the process object is written to the output stream. The user sees the string, but it's not saved in the variable or passed down the pipeline.
The information stream
The dilemma was how to fix the harmful aspects of Write-Host (can't suppress, capture, or redirect), but keep it from polluting the output stream. And of course, the solution must be backward compatible.
This most elegant solution is the information stream. In Windows PowerShell 5.0, you can send Write-Host output to the information stream. Because Write-Host still writes to the host program by default, the solution is backward compatible.
By using the information stream, you can suppress Write-Host messages:
You can capture:
And you can redirect:
Tip If you're not familiar with the 'n>&1' syntax, see about_Redirection.
Unless you intentionally redirect them, Write-Host messages still don't pollute the output stream.
Now if someone was to write a function like Get-PowerShellProcess (and you still should never do this), the end-user could suppress the host message.
Information stream features
Here are the features of the information stream in Windows PowerShell 5.0:
- $InformationPreference variable
Determines how Windows PowerShell manages the information stream.
Like the other stream preference variables, the value of $InformationPreference is an ActionPreference option:
Continue, Ignore, Inquire, SilentlyContinue, Stop, or Suspend. The default value is Continue.
- InformationAction common parameter
Determines how Windows PowerShell manages the information stream in the current command. This value takes precedence over the $InformationPreference for the current command.
Its value is also an Action Preference option:
Continue, Ignore, Inquire, SilentlyContinue, Stop, Suspend. The default value is Continue.
- InformationVariable common parameter
Saves the information stream in the specified variable. Enter a variable name without a dollar sign ( $ ).
Tip The variable name cannot be "host" because $host is an automatic variable (see about_Automatic_Variables).
- Write-Information cmdlet
The Write-Information cmdlet writes a message to the information stream. This message is not written to the console or sent to the host program, even when the $InformationPreference value is Continue. It responds to other values of InformationAction.
(This cmdlet behaves the way Write-Host probably should have from the start.)
Because Write-Information writes to the information stream, you can use the InformationVariable common parameter to capture its value.
If you really must write messages in a function or script, Write-Information won't pollute the information stream. (I had to add CmdletBinding to get the common parameters.)
As you learn Windows PowerShell 5.0, play around with the information stream. And the next time you're tempted to use Write-Host, use Write-Information instead.
~June
Thanks, June!
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