PowerShell Write-Host not synchronous

powershell

I'm writing a PowerShell script to check some properties of a server. When I execute the following cmdlets in order, the output is not displayed in the order I expect.

Write-Host "=== Operating System ==="
Get-WmiObject -computername $ServerName -class Win32_OperatingSystem | select Caption | ft -HideTableHeaders -AutoSize

Write-Host "=== Pagefile ==="
Get-WmiObject -ComputerName $ServerName -Class Win32_PageFileSetting

Write-Host "=== Locale ==="
Get-WmiObject -ComputerName $ServerName -class Win32_OperatingSystem | select Locale | ft -HideTableHeaders -AutoSize | Write-Output

Output:

=== Operating System ===

Microsoft Windows Server 2012 Standard

=== Pagefile ===

=== Locale ===

MaximumSize Name Caption
———– —- ——-
4000 C:\pagefile.sys C:\ 'pagefile.sys'

0813

How does it come that the pagefile output is not displayed under its title? It seems to me that Get-WmiObject is running asynchronously and immediately writes the next title (Locale).

How can I prevent this? It works when using Write-Output, but then I cannot use colored text.

Best Answer

Some of your text on-screen comes from objects going through the PowerShell pipeline, and some comes from Write-Host which prints to the screen immediately without touching the pipeline.

Gathering WMI information about the pagefile takes time and outputs to the pipeline, but the script has already moved on to printing the Locale message before that pipeline has finished.

This doesn't happen for (Operating System), because that pipeline finishes with ft -AutoSize (Format-Table), which pauses the script and waits for everything in the pipeline so it has as much information as possible when deciding how to size the columns. Once ft prints to the screen, then the script moves to the PageFile message.

You should use Write-Output instead to send the text through the pipeline, this way it will integrate well with other PowerShell features like redirection, collecting command output in files and variables.

Jeffrey Snover (PowerShell lead architect) has written about why Write-Host is not recommended on his blog here: http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/

Here's a link describing the behaviour of Format-Table:

Optimizing Column Width

Because the pipeline processes results in real time, PowerShell cannot know how wide of a space the column elements will occupy. As a result, it will tend to be generous in sizing columns. If you specify the -AutoSize parameter, Format-Table will collect all results first before setting the maximum width for all elements. You can optimize output, but the results will no longer be output in real time:

Master-PowerShell | With Dr. Tobias Weltner