I know this kind of feels like moving state in the "wrong direction" on the pipeline, but there are a few circumstances where this could be handy.
Is this code snippet possible?
if (Directed-To-Screen) {
Write-Host "Error!" -ForegroundColor Red
} else {
Write-Output "Error!"
}
Where Directed-To-Screen
would return $false if the current code/script is being piped to a variable or file, etc. (I know [Console]::ForegroundColor
\ $host.UI.RawUI.ForegroundColor
can be used to color Write-Output in some consoles).
There is actually quite a bit that could be done to improve formatting if its going to be printed on the screen, whereas piped output from utility functions should probably be structured so that individual fields can be consumed. Being able to tell them apart could be pretty useful. (There isn't a way to make a PSObject override its ToString formatting so that it appears all pretty when printed to the screen, is there?)
It might not even be possible to detect if its coming out on the screen or not. Can anyone confirm either way?
I think you are approaching this in the wrong way. Rather than using Write-Host
and forcing a red foreground colour you should output an object that displays in red on the terminal but just looks like plain text when written to a file.
There already is an object that does that: any object of type System.Management.Automation.ErrorRecord
will display as red if it reaches the end of the pipeline but can be written to a file. Unfortunately for your purposes it usually formats with CategoryId
and FullyQualifiedErrorId
fields, but it won't do that if the error object was created by a native command. We can fake that behaviour like this:
function Write-RedText
{
[CmdletBinding()]
[OutputType([int])]
Param
(
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
$Text
)
Begin
{
}
Process
{
foreach ($s in $Text)
{
#Wr$o = (Write-Error $s -ErrorId NativeCommandErrorMessage -TargetObject $None) 2>&1
$o = new-object -TypeName "System.Management.Automation.ErrorRecord" -ArgumentList ($s, "NativeCommandErrorMessage", [System.Management.Automation.ErrorCategory]::FromStdErr, "c")
$o | Add-Member -NotePropertyName writeErrorStream -NotePropertyValue $True
Write-Output $o
}
}
End
{
}
}
Now you can just do:
Write-RedText "Error!"
and it will appear in red if it reaches the host but just appears as plain text if it ends up in a file.
N.B. It is the writeErrorStream
property on the object that actually makes it display in red, so it is possible to make other objects display red as well just by adding that property. e.g.
$out = ls
$out | Add-Member -NotePropertyName writeErrorStream -NotePropertyValue $True
$out
will give you a directory listing that is red on the console, or if you prefer set the WriteWarningStream
property for orange text.
As to the rest of your question, I'm pretty sure there's no way to tell where the output will end up. There is an implicit | Out-Default
on the end of the outermost pipeline. Out-Default
formats the objects and sends them to the console, but there's no way to tell whether any objects reach that final command or if they do whether you've redefined Out-Default
to do something totally different.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments