I just came across a funny behavior when using Write-Host
on powershell.
What I wanted to do is get the colored output from Write-Host
and concurrently save the result in a variable. Checking other SO questions, led me to try the following:
$zz = &{
Write-Warning "hello"
Write-Error "hello"
Write-Output "hi"
} 3>&1 2>&1
$zz
#WARNING: hello
#Write-Error: hello
#hi
$zz = &{ Write-Host -ForegroundColor Red "[ERROR]: Package id: ""jaja"" not found!"; } 3>&1 2>&1
# [ERROR]: Package id: "jaja" not found!
$zz
# [nothing]
The output was surprising, and I could not find a way to have the output saved into a variable while also see it displayed, unlike when using the other Write-xxx
commandlets.
Q: What's gong on and how can I get both the output shown and save the results into a variable?
REFERENCES:
-
The conclusion seem to be that any coloring information is lost when using anything that has to do with redirecting output from
Write-Host
.
UPDATE-2
Interestingly, the color information are still "there" somewhere. Following mklement0's suggestion, I tried to save the color info for 2 different lines. But then the parsing is not correct, as shown below.
So with:
$captured = &{ Write-Host -ForegroundColor Red -NoNewline "[ERROR]: some error! " 6>&1; Write-Host -ForegroundColor Green "OKAY" 6>&1 }
We get:
CodePudding user response:
As explained in the answer you link to, you need redirection
6>&1
in order to captureWrite-Host
output (only works in PowerShell v5 and above):Write-Host
output captured via6>&1
consists of one or moreSystem.Management.Automation.InformationRecord
instances, which print as if they were strings, namely by their.MessageData.Message
property value, which is the string content of the argument(s) passed toWrite-Host
.Therefore, any coloring that stems from the use of the
-ForegroundColor
and-BackgroundColor
parameters is not (directly) passed through:- However, the information is preserved, namely in the
.MessageData.ForegroundColor
and.MessageData.BackgroundColor
properties, along with the information about whether-NoNewLine
was passed toWrite-Host
, in Boolean property.MessageData.NoNewLine
- However, the information is preserved, namely in the
By contrast, coloring via ANSI / VT escape sequences embedded in the original string argument(s) is preserved.
Thus, you can recreate the original coloring as follows - note that
Write-Host
is again used:$captured = Write-Host -ForegroundColor Red "[ERROR]: some error" 6>&1 $captured | ForEach-Object { $messageData = $_.MessageData $colorArgs = @{} if (-1 -ne $messageData.ForegroundColor) { $colorArgs.ForegroundColor = $messageData.ForegroundColor } if (-1 -ne $messageData.BackgroundColor) { $colorArgs.BackgroundColor = $messageData.BackgroundColor } Write-Host -Object $captured @colorArgs -NoNewline:$messageData.NoNewLine }