Write-Output or Write-Host in PowerShell
Learn if and when you should use Write-Output or Write-Host in PowerShell.
March 9, 2015
For more technical explainers on PowerShell, read our updated 2021 report: PowerShell 101: A Technical Explainer for IT Pros.
Q. Should I use Write-Host or Write-Output in my PowerShell?
A. If you open a PowerShell window and type the following commands the result is the same for both, it tells you hello:
PS C:> Write-Host ("Hello " + $env:USERNAME)Hello johnPS C:> Write-Output ("Hello " + $env:USERNAME)Hello john
It looks like they are the same but in reality they are working in very different ways. To understand this, it's best to take a short step back.
One of the great benefits of PowerShell is its pipeline mechanics that enable the output of one command to be passed to the next command in the pipeline. That output is not sent as basic text but rather the actual objects generated from a command are sent in the native object format to the next command. This is enabled for all commands (also referred to as Tokens) in a PowerShell pipeline and runs within a single instance of the PowerShell objectflow engine. This is best understood graphically as shown below.
In this example the pipeline is made up of four commands, each of which return data of varying types, such as process objects and so on. The first command runs until it produces data, at which point the data is delivered to the PowerShell engine. The PowerShell engine looks at the downstream command in the pipeline and examines the data requirements. Once determined, it then casts/coerces the data from the previous command into the correct format (where possible) to be passed to the subsequent command. This continues throughout all the existing commands in the pipeline. A command may accept data in many formats such as specific type of object, an integer ID or even a string name. The engine will do its best to take the data from the previous command and make it usable for the next command in the pipeline. For one of the accepted input data types, it starts with the type-specific input types first (IsA) and then on to more generic (HasA). For a more detailed explanation of the PowerShell pipeline I recommend watching http://channel9.msdn.com/shows/Going+Deep/Expert-to-Expert-Erik-Meijer-and-Jeffrey-Snover-Inside-PowerShell/.
So, what does this have to do with Write-Output and Write-Host? While Write-Output and Write-Host seemed to achieve the same result in our basic initial example, they are actually working very differently. This can be demonstrated with a more detailed example. Run the PowerShell script below. The script starts by creating creates a function to output whatever it is passed to the screen in a green color and then issues three commands. The first uses Write-Output which sends its data "this is a test" through the pipeline to our new Receive-Output function. The next uses Write-Host sending to the same function and finally Write-Output on its own without sending data to another command.
function Receive-Output { process { Write-Host $_ -ForegroundColor Green }}Write-Output "this is a test" | Receive-OutputWrite-Host "this is a test" | Receive-OutputWrite-Output "this is a test"
The output is shown below.
Notice that in the Write-Output example the text is output in green. What happened here is Write-Output wrote out "this is a test" as its output by delivering the content to the PowerShell engine. It then sent that data to the next command in the pipeline where it called the function that output that data in green.
In the Write-Host example the text is the standard default color. This is the fundamental difference. Write-Host does not output data to PowerShell Objectflow Engine but rather, as the name implies, writes directly to the host and sends nothing to the PowerShell engine to be forwarded to commands later in the pipeline.
Finally... notice that Write-Output also outputs to screen if there are no later commands in the pipeline. This is because at the end of every pipeline any data remaining is output to Out-Default which sends to Out-Host, i.e. it writes the data to the screen. Out-Default will automatically call a formatting cmdlet to ensure data can be displayed correctly. Don Jones has a nice article describing this in more detail at https://technet.microsoft.com/en-us/magazine/gg213852.aspx.
What this means is that if you only want data to display to the screen, use Write-Host. This has the advantage of nicer formatting options. To see this example, run the commands below.
Write-Host "You are looking " -NoNewlineWrite-Host "AWESOME" -ForegroundColor Red -BackgroundColor Yellow -NoNewlineWrite-Host " today"
Notice that you can control when new lines are used, configure the foreground and background colors, and so on. In fact its ONLY if you need the richer output for a user interface you should use Write-Host.
If you possibly want to write data to the screen, but also want the data to be passed down the pipeline to further commands, then use Write-Output. You may have also heard of echo, but this is just an alias for Write-Output (run 'Get-Alias echo' to confirm this).
Note that behind the scenes there are actually many different streams. In this FAQ I have focused on the Output/Success stream however there are separate streams for warnings, errors, debugging and verbose information. These are explained at http://blogs.technet.com/b/heyscriptingguy/archive/2014/03/30/understanding-streams-redirection-and-write-host-in-powershell.aspx.
It should be noted that for the most part you should use Write-Output as the goal for PowerShell is automation and Write-Host interferes with that automation and stops the output being able to be captured. Typically Write-Output is a better option and if you want to just convey information to users you can use Write-Verbose. The creator of PowerShell, Jeffrey Snover has a whole article on why Write-Host is (mostly) bad at http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/.
If you want a shorter, definitive answer without the explanation: you should use Write-Output unless you need rich display to a host for a user interface in which case use Write-Host.
About the Author
You May Also Like