Powershell: Write-Information results in InformationRecord being added to the Information stream unexpectedly in some cases

Created on 14 Sep 2020  路  7Comments  路  Source: PowerShell/PowerShell

Steps to reproduce

First run this in a new PowerShell session with -noprofile:

Write-Information 'Information'
Write-Verbose 'Verbose'
Write-Debug 'Debug'

Note how none of those produce any output, because each of their corresponding $*Preference variables is set to [System.Management.Automation.ActionPreference]::SilentlyContinue by default.

Now run this in the same session:

$ps = [powershell]::Create()
$ps.AddScript(@'
Write-Information 'Information'
Write-Verbose 'Verbose'
Write-Debug 'Debug'
'@).Invoke()
$ps.Streams.Verbose # Empty, as expected
$ps.Streams.Debug # Empty, as expected
$ps.Streams.Information # Not empty, and outputs "Information"...why?

Expected behavior

Both blocks of code would not output anything.

Actual behavior

The second block outputs the following text:

Information

Environment data

Name                           Value
----                           -----
PSVersion                      7.0.3
PSEdition                      Core
GitCommitId                    7.0.3
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
Issue-Question WG-Engine

All 7 comments

Some general comments on this: I have a C# project that runs PowerShell. I want to control the streams. When I put logic in place to allow the streams to be controlled, whether or not I have turned the Information stream "on", I get output from that stream, with no metadata to let me know if that output should show up or not. This seems like a bug, because InformationPreference is SilentlyContinue, just like it is for VerbosePreference and DebugPreference.

I have found a workaround for this, but it shouldn't be necessary, and I want to make sure it isn't doing something that I don't want to do. If I set InformationPreference to Ignore, the logic works as expected, and I can turn on Information stream output on demand within my script by using InformationAction on commands where I want that output. That workaround seems to be the only way that I can make the Information stream behave like it does in native PowerShell, but it shouldn't be necessary. Here is the above snippet with the workaround where I get the results that I expected in the first place:

$ps = [powershell]::Create()
$ps.AddScript(@'
$InformationPreference = [System.Management.Automation.ActionPreference]::Ignore
Write-Information 'Information'
Write-Verbose 'Verbose'
Write-Debug 'Debug'
'@).Invoke()
$ps.Streams.Verbose # Empty, as expected
$ps.Streams.Debug # Empty, as expected
$ps.Streams.Information # Empty, as expected

After discussing this in Discord, I bet this is probably due to the desire for Write-Host output to be capturable in the transcript, but if that is the desired result, the implementation is wrong because there is no use of Write-Host here.

Write-Information is by default also capturable in a transcript, even if it never appears on screen. I always assumed that was intentional.

It is not for Write-Host and not for a transcript. The code explicitly is if (preference != ActionPreference.Ignore) - write if not "Ignore". I believe it is by design and changing this would be huge breaking change since events are triggered there for other threads.

I suppose, why be consistent, right? Just because the error, warning, verbose, debug and progress streams can be silenced using System.Management.Automation.ActionPreference.SilentlyContinue, why should the information stream work the same way? That would make too much sense. 馃檮

The code is so simple that I can only say it is definitely by design and I don't know why. Perhaps someone from MSFT team knows this history.

@vexx32, the transcript behavior with respect to Write-Information has been fixed (after all, a transcript should not show different output than the console), though I'm not sure in what version exactly, and I'm not aware of an associated bug report (still affects Windows PowerShell; see also: #4645).

Let me try to summarize the troubling inconsistency (derived from observation, not source-code analysis):

  • Unlike with all other streams, SilentlyContinue for stream 6 (Write-Information) does _not_ suppress _writing to the stream at the source_.

  • Seemingly, it is unexpectedly left to the _host_ to enforce the silence _for display_.

This is easy to demonstrate: a redirection of stream 6 succeeds even with -InformationAction SilentlyContinue:

PS> Write-Information info -Infa SilentlyContinue 6>&1 | % { "[$_]" }
[info]  # !! stream output was still produced and redirected to the success stream.

To contrast this with the behavior of the Write-* cmdlets for the other streams:

'Write-Error', 'Write-Warning', 'Write-Verbose', 'Write-Debug', 'Write-Information' | % {
  $stream = ($_ -split '-')[-1]
  $htArgs = if ($stream -in 'Debug', 'Verbose') { # Boolean common parameters
    @{
      $stream = $false
    }
  } else { # enum-based common parameters
    @{
      ($stream + 'Action') = 'SilentlyContinue'
    }
  }
  $out = & $_ @htArgs $stream *>&1
  "redirected $stream`: [$out]"
}
redirected Error: []
redirected Warning: []
redirected Verbose: []
redirected Debug: []
redirected Information: [Information]
Was this page helpful?
0 / 5 - 0 ratings