{"id":5201,"date":"2015-07-04T00:01:00","date_gmt":"2015-07-04T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2015\/07\/04\/weekend-scripter-welcome-to-the-powershell-information-stream\/"},"modified":"2019-02-18T09:47:13","modified_gmt":"2019-02-18T16:47:13","slug":"weekend-scripter-welcome-to-the-powershell-information-stream","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/weekend-scripter-welcome-to-the-powershell-information-stream\/","title":{"rendered":"Weekend Scripter: Welcome to the PowerShell Information Stream"},"content":{"rendered":"<p><b style=\"font-size:12px\">Summary<\/b><span style=\"font-size:12px\">: Learn about the Windows PowerShell information stream in this guest post by June Blender.<\/span><\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. Today we have another guest blog post by Honorary Scripting Guy and Sapien technical evangelist, June Blender. Take it away June&#8230;<\/p>\n<p style=\"margin-left:30px\"><strong>Note<\/strong>&nbsp;&nbsp;This post is updated on August 3, 2015 for the Windows PowerShell 5.0.10240 preview. A previous version described the information stream features in Windows PowerShell 5.0.10018. This post introduces the new information stream in Windows PowerShell 5.0, and it explains the issue it tries to solve and its elegant solution.<\/p>\n<p>In March 2014, I wrote a Hey, Scripting Guy! Blog post, <a href=\"https:\/\/devblogs.microsoft.com\/scripting\/understanding-streams-redirection-and-write-host-in-powershell\/\" target=\"_blank\">Understanding Streams, Redirection, and Write-Host in PowerShell<\/a>, which explained the output streams in Windows PowerShell.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2134.wes-7-4-15-1.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2134.wes-7-4-15-1.png\" alt=\"Graphic\" title=\"Graphic\" \/><\/a><\/p>\n<p>The outlier in the stream world has always been the much-maligned <a href=\"http:\/\/go.microsoft.com\/fwlink\/p\/?linkid=294029\" target=\"_blank\">Write-Host<\/a> cmdlet. Windows PowerShell inventor, Jeffrey Snover decried it as&nbsp;<a href=\"http:\/\/www.jsnover.com\/blog\/2013\/12\/07\/write-host-considered-harmful\/\" target=\"_blank\">Write-Host Considered Harmful<\/a>. Famously, in his 2012 Scripting Games commentary, <a href=\"http:\/\/powershell.com\/cs\/blogs\/donjones\/archive\/2012\/04\/06\/2012-scripting-games-commentary-stop-using-write-host.aspx\" target=\"_blank\">Stop Using Write-Host!<\/a>, Windows PowerShell MVP and first follower, Don Jones, proclaimed that <b>Write-Host<\/b> kills puppies. That&rsquo;s a lot of high-powered condemnation for a cmdlet.<\/p>\n<p>It&rsquo;s all about to change. With the advent of the information stream in Windows PowerShell 5.0, <b>Write-Host<\/b> is being redeemed. Actually, it&#039;s being, well&#8230;mainstreamed. And, Windows PowerShell 5.0 includes a new cmdlet, <a href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkId=525909\" target=\"_blank\">Write-Information<\/a>, that has the benefits of <b>Write-Host<\/b> without the costs.<\/p>\n<h2>Write-Host and streams<\/h2>\n<p>The root of the problem is that in Windows PowerShell versions 1.0 through 4.0, <b>Write-Host <\/b>output doesn&rsquo;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.<\/p>\n<p>Because <b>Write-Host<\/b> doesn&#039;t go to a stream, if you put <b>Write-Host<\/b> in a script, the end-user can&#039;t suppress it, can&#039;t save it, and can&#039;t redirect it.<\/p>\n<ul>\n<li>You can&#039;t suppress <b>Write-Host<\/b> output because there&#039;s no preference that silences it.<\/li>\n<li>You can&rsquo;t save <b>Write-Host<\/b> output in a variable, because the assignment operator uses the output stream. The <b>Write-Host<\/b> output is written to the host program, but the variable is empty.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4061.2.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4061.2.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<ul>\n<li>You can&#039;t pass <b>Write-Host<\/b> output down the pipeline, because only the output stream goes down the pipeline.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7673.3.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7673.3.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<ul>\n<li>You can&#039;t redirect <b>Write-Host<\/b> output, because redirection sends output from one stream to another, and <b>Write-Host<\/b> isn&#039;t part of any stream.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4150.4.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4150.4.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<h2>Write-Host and stream pollution<\/h2>\n<p>Despite this very high-level condemnation, people kept using <b>Write-Host<\/b>, precisely because it doesn&#039;t go to the output stream. <b>Write-Host<\/b> is eco-friendly, because it doesn&#039;t pollute the output stream.<\/p>\n<p>The underlying principle is that every command should generate one type of output. For example, <b>Get-Process<\/b> returns <i>Process<\/i> objects, and <b>Start-Job<\/b> returns <i>PSRemotingJob<\/i> objects.<\/p>\n<p>You never want a command like the following, which returns process objects and a string:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2772.5.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2772.5.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>In its own sad way, <b>Write-Host<\/b> solves this problem. In this version, I replaced <b>Write-Output<\/b> with <b>Write-Host<\/b>. Now this function writes a process object and a string, but only the process object is written to the output stream. Typically, the user sees the string, but it&#039;s not saved in the variable or passed down the pipeline.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7762.6.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7762.6.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<h2>Write-Information and the information stream<\/h2>\n<p>The dilemma was how to fix the harmful aspects of <b>Write-Host<\/b> (can&#039;t suppress, capture, or redirect), but keep it from polluting the output stream. And of course, the solution must be backward compatible.<\/p>\n<p>This most elegant solution is provided by the information stream and the <b>Write-Information<\/b> cmdlet. The <i>information stream<\/i> is a new output stream that works much like the error and warning streams.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3482.7.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3482.7.png\" alt=\"Graphic\" title=\"Graphic\" \/><\/a><\/p>\n<p>With these new features, you can write messages to the user without polluting the information stream. And you can suppress the messages, capture them, save them, and redirect them.<\/p>\n<p>The information stream has a preference variable, <b>$InformationPreference<\/b>, with a default value of <b>SilentlyContinue<\/b>, and a common parameter, <b>InformationAction<\/b>, to override the preference for the current command. It also has an <b>InformationVariable<\/b> common parameter that saves the stream content in the specified variable.<\/p>\n<p>The new cmdlet,<b> Write-Information<\/b>, provides information to the user without polluting the output stream. I think of it as a do-over of <b>Write-Host<\/b>. Both <b>Write-Host<\/b> and <b>Write-Information<\/b> write to the information stream, but they behave differently, because <b>Write-Host<\/b> must be backward compatible.<\/p>\n<p><b>Write-Information<\/b> writes <b>InformationRecord<\/b> objects (System.Management.Automation.InformationRecord) to the information stream. Its output is determined by the <b>$InformationPreference<\/b> variable, which is set to <b>SilentlyContinue<\/b> by default. So, by default, its output is suppressed.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3108.8.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3108.8.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>To display a <b>Write-Information<\/b> message, change the default value of the <b>$InformationPreference<\/b> variable, or use a value of <b>Continue<\/b> for the new <b>InformationAction<\/b> common parameter.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5543.9.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5543.9.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p><b>Write-Host<\/b> also writes <b>InformationRecord<\/b> objects to the information stream, but it is not affected by the <b>$InformationPreference<\/b> variable or the <b>InformationAction<\/b> common parameter. (Windows PowerShell 5.0 is still in preview, so this might change.)<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4035.10.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4035.10.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>However, you can save the content of <b>Write-Host<\/b> and <b>Write-Information <\/b>output in a variable by using the new <b>InformationVariable<\/b> common parameter.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/8461.11.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/8461.11.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Because they write to the information stream (stream #6), you can redirect the output of <b>Write-Host<\/b> and <b>Write-Information<\/b> to a file. (Notice that redirecting host output suppresses it. Windows PowerShell 5.0 is still in preview, so this might change.)<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1651.12.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1651.12.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>You can also redirect output from the information stream (stream #6) to standard output (stream #1). (For help, see <a href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkID=113254\" target=\"_blank\">about_Redirection<\/a>.) Redirecting to standard output lets you use the assignment operator.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5277.13.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5277.13.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Then you can pass content from the information stream down the pipeline, such as to the <a href=\"http:\/\/go.microsoft.com\/fwlink\/p\/?linkid=293971\" target=\"_blank\">Get-Member<\/a> and <a href=\"http:\/\/go.microsoft.com\/fwlink\/p\/?linkid=294007\" target=\"_blank\">Select-Object<\/a> cmdlets.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/15.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/15.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Unless you intentionally redirect them, <b>Write-Information<\/b> and <b>Write-Host<\/b> messages still don&#039;t pollute the output stream.<\/p>\n<p>Now if someone was to write a function, such as <b>Get-PowerShellProcess<\/b> (and you still should never do this), the information is suppressed by default and the end-user could display the information without polluting the output stream. (I had to enable cmdlet binding to get the common parameters.)<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/16.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/16.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<h2>Write-Host vs. Write-Information<\/h2>\n<p>As you adopt <b>Write-Information<\/b>, keep in mind that there are a few differences:<\/p>\n<ul>\n<li><b>Write-Information<\/b> responds to the values of the <b>$InformationPreference<\/b> variable and the <b>InformationAction<\/b> common parameter. <b>Write-Host<\/b> does not.<\/li>\n<li><b>Write-Host<\/b> has parameters that change its display, for example, <b>ForegroundColor<\/b> and <b>BackgroundColor<\/b>. <b>Write-Information<\/b> does not.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/17.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/17.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<ul>\n<li><b>Write-Information<\/b> has a <b>Tags<\/b> parameter like <b>New-ModuleManifest<\/b> and cmdlets in the <b>AzureResourceManager<\/b> module. <b>Write-Host<\/b> does not.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/18.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/18.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<ul>\n<li><b>Write-Host<\/b> takes value from the pipeline. <b>Write-Information<\/b> does not.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/19.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/19.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>As you learn Windows PowerShell&nbsp;5.0, play around with the information stream. And the next time you&#039;re tempted to use <b>Write-Host<\/b>, use <b>Write-Information<\/b> instead.<\/p>\n<p>~June<\/p>\n<p>Thanks, June!<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b><span style=\"font-size:12px\">&nbsp;<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 and Sapien technical evangelist, June Blender. Take it away June&#8230; Note&nbsp;&nbsp;This post is updated on August 3, 2015 for the Windows PowerShell [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[51,56,370,600,3,61,45],"class_list":["post-5201","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-getting-started","tag-guest-blogger","tag-june-blender","tag-powershell-5-0","tag-scripting-guy","tag-weekend-scripter","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>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 and Sapien technical evangelist, June Blender. Take it away June&#8230; Note&nbsp;&nbsp;This post is updated on August 3, 2015 for the Windows PowerShell [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/5201","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=5201"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/5201\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=5201"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=5201"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=5201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}