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-Hostthe 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-Hostthe parameters are packed up and passed toWrite-Informationas aHostInformationMessage Write-Informationwill process the parameters as a special type if- A tag of
PSHOSTexists and a tag ofFORWARDEDdoes not - or The current preference variable is
Continue
- A tag of
We can therefore conclude:
Passing a
HostInformationMessagewith noPSHOSTtag 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 *