According to the MSDN for Strongly Encouraged Development Guidelines:
Cmdlets should not use the Console API.
Why is this?
The main reason you shouldn't use console-related functionality is that not all PowerShell host environments are consoles.
While the typical use case is to run PowerShell in a console, PowerShell does not need a console and can cooperate with different kinds of host environments.
Thus, for your code to remain portable, it shouldn't assume the existence of a console.
It is safe, however, to assume the existence of (the abstraction called) host, which PowerShell exposes via the automatic $HOST
variable.
The capabilities of hosts vary, however, which has historically created problems even when not using the console API directly, but its PowerShell abstraction, Write-Host
- see below.
PowerShell provides a hosting API,
with which the PowerShell runtime can be embedded inside other applications. These applications can then use PowerShell functionality to implement certain operations, including those exposed via the graphical interface.
https://en.wikipedia.org/wiki/PowerShell
The regular PowerShell console using the Console Window Host (conhost.exe
) on Windows is therefore just one implementation of a PowerShell host - the PowerShell ISE is another example, as is the Microsoft Exchange Server management GUI (2007+).
As for Write-Host
:
Up to PSv4, as the name suggests, it used to write to the host - which may or may not be a console - so Write-Host
could actually fail on hosts that don't support user interaction; see this question.
Starting with PSv5, Write-Host
is safe to use, because it now writes to the newly introduced, host-independent information stream (number 6
) - see Get-Help about_Redirection and the next section.
Note that Write-Host
still does and always has generated output outside of the normal PowerShell output stream - its output is meant to be "commentary" (feedback to the user) rather than data.
While Write-Host
is safe to use in PSv5+, it exist for backward compatibility, so instead consider using
Write-Information -InformationAction Continue
or using Write-Information
with preference variable $InformationPreference
set to Continue
, because:
"Write-Host" is now a bit of a misnomer, given that it doesn't actually directly write to the host anymore.
Write-Host
, in the interest of backward compatibility, doesn't integrate with the $InformationPreference
preference variable - see below.
Write-Host
still offers console-inspired formatting parameters (-ForegroundColor
, -BackgroundColor
), which not all hosts (ultimately) support.
Write-Host
vs. Write-Information
:
Tip of the hat to PetSerAl for his help with the following.
Write-Information, introduced in PSv5, is the cmdlet that fully integrates with the new, host-independent information stream (number 6
).
Notably, you can now redirect and thus capture Write-Information
/ Write-Host
output by using 6>
, something that wasn't possible with Write-Host
in PSv4-.
Also note that this redirection works even with $InformationPreference
's default value, SilentlyContinue
, which only governs the display, not the output aspect (only using common parameter -InformationAction Ignore
truly suppresses writing to the stream).
In line with how PowerShell handles errors and warnings, the display behavior of Write-Information
is controllable via the new $InformationPreference
preference variable / the new common -InformationAction
cmdlet parameter.
Write-Information
's default behavior is to be silent - $InformationPreference
defaults to SilentlyContinue
.
Note that Write-Information
has no direct formatting parameters[1] and instead offers keyword tagging with the -Tags
parameter[2]
.
By contrast, for backward compatibility, Write-Host
effectively behaves like
Write-Information -InformationAction Continue
, i.e., it outputs by default, and the only way to silence it is to use Write-Host -InformationAction Ignore
[3]
- it does not respect an $InformationPreference
value of SilentlyContinue
(it does, however, respect the other values, such as Inquire
).
[1] PetSerAl points out that you can pass formatting information to Write-Information
, but only in an obscure fashion that isn't even documented as of PSv5.1; e.g.:
Write-Information -MessageData ([System.Management.Automation.HostInformationMessage] @{Message='Message'; ForegroundColor='Red'}) -InformationAction Continue
[2] Note how parameter name "Tags" actually violates one of the strongly encouraged cmdlet development guidelines: it should be "Tag" (singular).
[3] PetSerAl explains that this behavior stems from Write-Host
passing the PSHOST
tag to Cmdlet.WriteInformation behind the scenes.