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>&1in order to captureWrite-Hostoutput (only works in PowerShell v5 and above):Write-Hostoutput captured via6>&1consists of one or moreSystem.Management.Automation.InformationRecordinstances, which print as if they were strings, namely by their.MessageData.Messageproperty value, which is the string content of the argument(s) passed toWrite-Host.Therefore, any coloring that stems from the use of the
-ForegroundColorand-BackgroundColorparameters is not (directly) passed through:- However, the information is preserved, namely in the
.MessageData.ForegroundColorand.MessageData.BackgroundColorproperties, along with the information about whether-NoNewLinewas 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-Hostis 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 }


