Write-Information With Colours
When learning PowerShell, one of the first things you learn is that the command
Write-Host
is super useful. It lets you write messages to the console and
allows you to specify optional foreground and background colors.
However, the very next thing you learn is:
Don’t use
Write-Host
- it can’t be suppressed or redirected.
So how do you write messages to the user?
Write-Information
In PowerShell 5, a new stream was introduced. PowerShell already had Verbose, Debug, Warning, Error, and Output streams, but it was now time to add an Information stream. Ed Wilson has a great write-up on its introduction here.
Why?
One of the key problems with Write-Host
is that it goes directly to the host
implementation. There it is consumed and effectively ‘lost’ to the user.
By introducing Write-Information
and the new stream, users
can now redirect the stream and modify its impact using $InformationPreference
and the common parameter -InformationAction
for cmdlets.
With the new stream available, the implementation of Write-Host
was then changed
to redirect to Write-Information
. To make the changes non-breaking the
-InformationAction
is always treated as Continue
to ensure that
existing uses of Write-Host
continue to display as they did in previous
versions of PowerShell.
This means:
If a cmdlet calls
Write-Host
the user can never hide that message from the console.
For example, all of these messages are still displayed even when attempting to
use $InformationPreference
and -InformationAction
But what about colours?
However, Write-Host
supports -ForegroundColor
and -BackgroundColor
but
Write-Information
does not. People continue to use
Write-Host
and in doing so they continue to prevent the user from using
$InformationPreference
and -InformationAction
as intended.
How is Write-Host
implemented?
So how can we use the information stream and also have colours? Let’s take a
look at the source code to see how Write-Host
is now implemented.
NOTE: This isn’t the actual Windows PowerShell version of the code, but by checking the PowerShell Core implementation we should get a handle on how things currently work as well as how things work in the future.
The full implementation of Write-Host
can be seen here. We’re actually
just interested in the implementation of ProcessRecord
.
What we can see is the construction of a HostInformationMessage
object
containing the parameters from the cmdlet. This is then passed on to WriteInformation
along with a tag of PSHOST
.
Taking a look at the implementation for Write-Information
we can see that the tags are checked to see if the the PSHOST
tag is provided and a tag of
FORWARDED
is missing or the current information preference is Continue
.
In the event that this check is passed, the MessageData
of the current record
is tested as a HostInformationMessage
and if found, the message is then
decomposed and its values used to communicate to the host.
Before all of these checks, there is a call to CBhost.InternalUI.WriteInformationRecord(record);
where (I assume…) the normal writing of the record occurs.
From this information we now understand:
- When calling
Write-Host
the parameters are packed up and passed toWrite-Information
as aHostInformationMessage
Write-Information
will process the parameters as a special type if- A tag of
PSHOST
exists and a tag ofFORWARDED
does not - or The current preference variable is
Continue
- A tag of
We can therefore conclude:
Passing a
HostInformationMessage
with noPSHOST
tag will ensure only the preference variable impacts visibility.
Write-InformationColored
Taking everything we’ve learnt so far, we can now build a function that will support user-specified colours when viewed in a console, but also honour the visibility of the information stream:
By using the new function, we get all the benefits of the information stream
and its associated preference variable as well as the simple coloured output
that Write-Host
also supports.
You can grab all the examples from this post here
Leave a Comment
Your email address will not be published. Required fields are marked *