Powershell: WarningVariable incorrect output

Created on 20 Feb 2020  路  2Comments  路  Source: PowerShell/PowerShell

Steps to reproduce

function Test-Warning
{
    [CmdletBinding()]
    param ()

    Write-Warning -Message "Test-Warning"
}

Test-Warning -WarningVariable SS -WarningAction "SilentlyContinue"
$SS

Expected behavior

Expected is yellow warning with the WARNING label

WARNING: Test-Warning

Actual behavior

Actual behavior is just the plain white text, as if we used plain Write-Host

Test-Warning

Environment data

$PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.0.0-rc.2
PSEdition                      Core
GitCommitId                    7.0.0-rc.2
OS                             Microsoft Windows 10.0.18363
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Why is expected behavior Yellow text with WARNING label?

Because if we repeat exactly the same code with Write-Error we will get the expected behavior,
which is both red and formatted text:

function Test-Error
{
    [CmdletBinding()]
    param ()

    Write-Error -Message "cmdlet error"
}
Test-Error -ErrorVariable SS -ErrorAction "SilentlyContinue"
$SS

Actual and expected behavior

Write-Error: C:\Users\haxor\GitHub\whatever.ps1:84:1
Line |
  84 |  Test-Error -ErrorVariable SS -ErrorAction "SilentlyContinue"

     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | cmdlet error

Note

If you run Get-Member on SS variable the result is normal:

System.Management.Automation.ErrorRecord
System.Management.Automation.WarningRecord

I didn't test this with Write-Debug, Write-Verbose etc. ie. by using preference variables.

Also for example Write-Information is not affected by this since there is no INFO label and text is not colored anyway, but it would be great if informational messages get some formatting too.

Issue-Question

Most helpful comment

Hi @metablaster
The coloring for all types of data records is done by the host (console host) so if you use the appropriate Write-* you get the appropriate coloring. You can see this by instantiating a WarningRecord

{master} PSCore (1:34) >  [System.Management.Automation.WarningRecord]::new("Hello")
Hello
{master} PSCore (1:35) >  Write-Warning ([System.Management.Automation.WarningRecord]::new("Hello")) ; write the warning record
WARNING: Hello

So the color & prefix does not generally depend on the _type_ of object, it depends on the _disposition_ of the object.

Except for error records that is :-) Because of the way the Console Host muxes and demuxes error and output records, things of type ErrorRecord are always printed in red even when displayed through stdout.

{master}PSCore (1:42) >  $ev =  [System.Management.Automation.ErrorRecord]::new([exception]::New("exception yo!"), "123", "NotImplemented", $null)
{master}PSCore (1:43) >  $ev

NotImplemented: exception yo! #<-- this shows up in read.
{master}PSCore (1:44) >

Part of the reason things work the way they do is because the non-error information streams were originally simple strings, not instances of a particular type. Over the years, they turned into rich objects but the color-handling code hasn't changed (much).

So you can argue that not automagically coloring the various data record is wrong. But you can also argue that the behaviour for ErrorRecord is wrong. IMHO either behaviour is probably fine as is the current mixed behaviour.

All 2 comments

Hi @metablaster
The coloring for all types of data records is done by the host (console host) so if you use the appropriate Write-* you get the appropriate coloring. You can see this by instantiating a WarningRecord

{master} PSCore (1:34) >  [System.Management.Automation.WarningRecord]::new("Hello")
Hello
{master} PSCore (1:35) >  Write-Warning ([System.Management.Automation.WarningRecord]::new("Hello")) ; write the warning record
WARNING: Hello

So the color & prefix does not generally depend on the _type_ of object, it depends on the _disposition_ of the object.

Except for error records that is :-) Because of the way the Console Host muxes and demuxes error and output records, things of type ErrorRecord are always printed in red even when displayed through stdout.

{master}PSCore (1:42) >  $ev =  [System.Management.Automation.ErrorRecord]::new([exception]::New("exception yo!"), "123", "NotImplemented", $null)
{master}PSCore (1:43) >  $ev

NotImplemented: exception yo! #<-- this shows up in read.
{master}PSCore (1:44) >

Part of the reason things work the way they do is because the non-error information streams were originally simple strings, not instances of a particular type. Over the years, they turned into rich objects but the color-handling code hasn't changed (much).

So you can argue that not automagically coloring the various data record is wrong. But you can also argue that the behaviour for ErrorRecord is wrong. IMHO either behaviour is probably fine as is the current mixed behaviour.

@BrucePay Thank you for detailed explanation!
So basically we need to Write-Warning again to format the output.

I understand that the additional reason (to one you explained) why Write-Error is an exception is because if we would be required to Write-Error again just to get formatted output then the $Error automatic variable would contain duplicate data.

Since other streams do not have associated automatic variables this is not a problem.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JohnLBevan picture JohnLBevan  路  3Comments

andschwa picture andschwa  路  3Comments

MaximoTrinidad picture MaximoTrinidad  路  3Comments

Michal-Ziemba picture Michal-Ziemba  路  3Comments

aragula12 picture aragula12  路  3Comments