Writing Output with PowerShell


Summary: Microsoft PowerShell MVP, Marco Shaw, discusses writing output from Windows PowerShell.

Microsoft Scripting Guy, Ed Wilson, is here. Today we will be joined by Marco Shaw.

Photo of Marco Shaw

Marco is a consultant with CGI in Moncton. He has been working in the IT industry for over 12 years, also working for Bell Aliant and Atlantic Lottery. He was awarded the Microsoft MVP award for his contributions to the Windows PowerShell community in 2007, 2008, 2009, and 2010. His recent authoring activities have included writing Windows PowerShell content for a Windows Server 2008 book published by Microsoft Press and writing a Windows PowerShell-related article on System Center Operations Manager 2007 for TechNet Magazine. He also provided Windows PowerShell content for a SQL Server 2008 book by SAMs publishing company and for a just released revised edition of System Center Operations Manager 2007 Unleashed by SAMs. He also coauthored the 2nd edition of PowerShell Unleashed published by SAMs, which was released early in 2009. He has spoken at Microsoft TechDays in Halifax, Canada the last two years where he has delivered sessions on System Center Operations Manager 2007 R2, Windows Server 2008 R2, and Windows PowerShell.

Using Write-Host and Write-Output

When writing scripts, I’ll typically use simple quotation marks to wrap anything I want to display on the screen, but there are two cmdlets in particular that provide some extra features and can be very useful when creating scripts: Write-Host and Write-Output.

Of the two, Write-Host is typically the only one I frequently use—in particular with its NoNewLine switch. What NoNewLine provides is a simple way to join different lines together.

Here is a simple code example to demonstrate:

Write-Host –NoNewLine “Counting from 1 to 9 (in seconds): 

foreach($element in 1..9){

  Write-Host –NoNewLine  “${element} “

  Start-Sleep –Seconds 1


Write-Host “”

The following image shows the output of running the script. If you try running the script on your own, you will notice that it appears to be a simple counter.

Image of command output

Now, there are countless ways I could have accomplished this, for example, building a simple string or simply clearing the screen each time.

Something else that Write-Host is useful for is when one might want to add color in their output. This can be very useful when trying to make output stand out or even just to get really flashy stuff on screen. I am going to build on the previous code snippet and blend in some colors as the numbers change.

Write-Host –NoNewLine “Counting from 1 to 9 (in seconds): 

foreach($element in 1..3){

  Write-Host –NoNewLine  “${element} ” -BackgroundColor “Green” -ForegroundColor “Black”

  Start-Sleep –Seconds 1


foreach($element in 4..6){

  Write-Host –NoNewLine  “${element} ” -BackgroundColor “Yellow” -ForegroundColor “Black”

  Start-Sleep –Seconds 1


foreach($element in 7..9){

  Write-Host –NoNewLine  “${element} ” -BackgroundColor “Red” -ForegroundColor “Black”

  Start-Sleep –Seconds 1


Write-Host “”

The following image shows the result of running the previous code. The coloring uses good old traffic light colors to show the progression in groups of three. I have also changed the color in the text displayed on the console to make it clearer to see against the background colors.

Image of command output

OK, that was fun…

Now, let us dig a bit deeper. In Windows PowerShell, the host is what you, as a user, interact with. You will typically interact with the two default hosts: the Windows PowerShell console and the Windows PowerShell Integrated Scripting Environment (ISE).

When you use Write-Host, you are telling Windows PowerShell to simply display something in the host to the user. But what happens with Write-Host output if I’m running a script from a scheduled task or even if I do something simple like redirect my script by using the standard redirection operator (>)? In these cases, (an example is coming up), what Write-Host prints out is basically lost. In other words, if you are not watching your script when it actually is running, Write-Host is not doing a whole lot for you. Basically, it is displaying information to the screen, and then “throwing it away.”

There is an excellent example that Don Jones’ wrote a few years ago (for more information, see Welcome to Concentrated Technology). You can see this by looking over the following image.

Image of command output

In the previous image, I have used several commands. The important thing to notice between the first and second command is that in the first one, it appears that the Where-Object cmdlet doesn’t work! In fact, it is working fine, and just doing what it is told. The important thing to note is what I said about Write-Host “displaying stuff and throwing it away.” Write-Host is the cmdlet that is responsible for displaying the numbers on the screen, and Where-Object actually gets nothing at all sent to it because of the use of Write-Host.

In the second command, things work as one might expect. The objects are passed along the pipeline so Where-Object actually works in this case, and it is able to filter the objects properly because Write-Output was used instead.

The above image also shows the output from a third and fourth command. They are included to show how Write-Output is basically always there without having to be explicitly added. Windows PowerShell does a lot of things behind the scenes for you, and this is just one example of this.

Another simple example to show the contract between the two cmdlets is to show an example that uses output redirection. Consider the following code snippet.

Write-Host “Phase 1”


Write-Output $start

Write-Host “Phase 2”

Start-Sleep -Seconds 5

Write-Host “Phase 3”


Write-Output $end

Write-Host “Phase 4”

$diff=New-TimeSpan $start $end

Write-Output $diff

The following image shows this script being run two different ways.

Image of command output

As can be seen in this image, Write-Host really does just that, and nothing more.

I hope that I have helped clarify the differences between the two cmdlets, and when you might look to use one versus the other depending on what you are trying to accomplish.

Thanks you, Marco, for helping to clarify some of the confusion between when to use Write-Host and when to use Write-Output.

The 2011 Scripting Games Wrap-up Week will continue tomorrow when our guest blogger, Bartek Bielawski, talks the 2011 Scripting Games.

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