You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Out-Default -Transcript only suppresses the display of the success output stream #11135
The purpose of Out-Default -Transcript is to record its input in the transcript only, without also printing it to the host (console). [Update: At least that's the inferred purpose, based on its behavior with success output].
Given that all output streams are transcribed, it would make sense to also suppress host output for all streams. However, only the success output stream is currently silenced.
Note that this and the other related issues are likely due to exactly how Out-Default is utilized by the host. Whatever PSHost is currently in control of the REPL loop typically takes the typed string and creates a merged output Command from it. Out-Default is then added to the pipeline.
Here is more or less how both PowerShellEditorServices and pwsh's ConsoleHost handle pipeline creation:
Tbh I thought that parameter was meant to be used by application hosts, not necessarily for scripts. Do you know of a place that this use case is documented?
FWIW: It seems very purposeful that the other streams are not affected:
Thanks for the source-code link; yes, it looks like it's intentional, but I think that behavior is problematic:
(a) conceptually, for its asymmetry: if all streams are being transcribed, why would you only display-silence one of them?
(b) due to the inability to display-silence the other streams even with workarounds.
Do you know how application hosts use it, and if changing the behavior to display-silence all streams would be more than a hypothetical breaking change?
Of course, one way to resolve this would be to document the limitation and move on...
Thanks for the source-code link; yes, it looks like it's intentional, but I think that behavior is problematic:
(a) conceptually, for its asymmetry: if all streams are being transcribed, why would you only display-silence one of them?
I presume it's because they're displaying the output stream in a different way. Like I said -Transcript also works like -PassThru does for most cmdlets.
Lets say there is a host application that displays output in a table, sorta like Out-GridView. In order for it to do that it would need the objects returned as they are. Typically, when the host is told to write output lines, it's already been transformed into strings by the format engine. With this switch, it can write the output to the transcript as if it were a normal console, while still displaying the results how it wants to.
In that scenario, the host is very unlikely to actually want a full ErrorRecord, it's probably perfectly happy just writing that error message out in a box somewhere in the same format it would be written to the console.
(b) due to the inability to display-silence the other streams even with workarounds.
Well sorta. The example I gave would still work if you added | Where-Object { $_ -isnot [ErrorRecord] } and etc for the other streams.
Do you know how application hosts use it, and if changing the behavior to display-silence all streams would be more than a hypothetical breaking change?
Yeah probably. I don't think that parameter was meant to be used by anything other than hosts. In my opinion, it only makes sense for hosts because the intent is that the output is displayed some other way. A transcript is meant to be a recording of a session, purposefully avoiding that seems counter to the point of it to me. Are you trying to use transcripts for script logging?
Of course, one way to resolve this would be to document the limitation and move on...
Honestly I'd say throw DontShowAttribute on it, assuming that my understanding of it's purpose is correct. If this parameter doesn't make sense for any consumer other than a host application, maybe it shouldn't show up in tab completion.
That's what makes the example I gave work. You take responsibility for displaying the output stream, but you still write to the transcript as if it were displayed normally.
Just to be perfectly clear though, I've never once used it nor have I ever even seen it used. I'm realizing my wording may have implied differently. This is all just what I'm inferring based on it's behavior of the switch and the design of transcripts.
Some context: when we were designing the console host experience we realized that we had a problem. With split streams, displaying them individually (I.e. separated) meant that you wouldn't get errors in context which was bad for a console experience. To solve this we added a feature in the pipeline processor to merge the error output from all of the prior commands into the output stream. Then we created Out-Default to take the merged output, demultiplex the records and render them appropriately. This cmdlet was really only intended to be used by the host. I assume (but don't know) since everything went through Out-Default this was the natural place to insert transcription.
(Note: none of this applied to native commands in the terminal position in a pipeline. In that case, the subprocess received the console host io handles allowing them to write directly to a console. This was necessary so that things like vim.exe could work from PowerShell.exe. This also meant that output from native commands in this situation was not captured in the transcript.)
It seems that (b) can be answered for parameter-less use of Out-Default: do not use it as an end user - the primary reason it exists as a user-callable cmdlet is so you can override it with a custom implementation.
Additionally, we need to establish whether it makes sense for end users to call Out-Default with -Transcript (its only cmdlet-specific parameter):
I had inferred the purpose of -Transcript as allowing end users to write to the transcript only, without also printing to the host.
You can use it that way, but only for the success output stream.
Based on my assumption about the purpose, I asked for all streams to be host-silenced, to better embody that purpose.
Patrick Meinecke (@SeeminglyScience) provided an alternative explanation, which sounds more plausible to me: that -Transcript is really meant for use by application hosts; to quote him: "You take responsibility for displaying the output stream, but you still write to the transcript as if it were displayed normally."
If we find that direct calls to Out-Defaultnever make sense, we can close this issue; unfortunately, #11134 remains an issue either way, because it also affects Out-Host, for which there are legitimate uses.
none of this applied to native commands in the terminal position in a pipeline.
It does apply to native commands in the context of transcribing, however, as evidenced by stderr output by default properly showing up in transcripts.
In other words: while transcribing, the direct-to-host behavior is intentionally disabled so as to be able to capture all output in the transcript.
Another way of demonstrating that is to start a transcript and then try to invoke vim; what you'll see is the following warning (on macOS), followed by a blank line:
Vim: Warning: Output is not to a terminal
(Type :q<Enter> to exit Vim or buy
).
As an aside: Note that after exiting Vim in this scenario the PSReadline bindings (arrow keys) don't work until you run cls.
/// <summary>/// Determines whether objects should be sent to API consumers./// This command is automatically added to the pipeline when PowerShell is transcribing and/// invoked via API. This ensures that the objects pass through the formatting and output/// system, but can still make it to the API consumer./// </summary>[Parameter()]publicSwitchParameterTranscript{get;set;}
Out-Default is used internally and should not be called directly.
I wouldn't use the term internally. It's intended to be used by host applications. Said host applications do not have to be made internally for it's use to be considered supported.
Activity
SeeminglyScience commentedon Nov 20, 2019
Note that this and the other related issues are likely due to exactly how
Out-Defaultis utilized by the host. WhateverPSHostis currently in control of the REPL loop typically takes the typed string and creates a merged outputCommandfrom it.Out-Defaultis then added to the pipeline.Here is more or less how both PowerShellEditorServices and pwsh's
ConsoleHosthandle pipeline creation:I imagine you can also just do a standard redirect, I'm not sure if there would be any behavioral differences:
mklement0 commentedon Nov 20, 2019
Thanks, Patrick Meinecke (@SeeminglyScience), that's helpful background information.
Re:
Unfortunately, this workaround still doesn't manage to silence the display of all streams, which is the intent here: the error still prints.
That
-Transcriptshouldn't pass streams through to the host is the reason for creating this issue.If you omit the
$null =,*>&1then causes all streams other than the success streams to produce duplicate host output.The only scenario in which the
*>&1workaround is effective is for external programs (no$null =needed):SeeminglyScience commentedon Nov 20, 2019
Tbh I thought that parameter was meant to be used by application hosts, not necessarily for scripts. Do you know of a place that this use case is documented?
FWIW: It seems very purposeful that the other streams are not affected:
PowerShell/src/System.Management.Automation/FormatAndOutput/out-console/ConsoleLineOutput.cs
Lines 310 to 338 in 2c8955e
mklement0 commentedon Nov 20, 2019
No, the
Out-Defaulthelp topic is woefully terse.Thanks for the source-code link; yes, it looks like it's intentional, but I think that behavior is problematic:
(a) conceptually, for its asymmetry: if all streams are being transcribed, why would you only display-silence one of them?
(b) due to the inability to display-silence the other streams even with workarounds.
Do you know how application hosts use it, and if changing the behavior to display-silence all streams would be more than a hypothetical breaking change?
Of course, one way to resolve this would be to document the limitation and move on...
mklement0 commentedon Nov 20, 2019
P.S.: It's perfectly possible that
-Transcriptwas never designed for the use case I have in mind - again, documentation would help.SeeminglyScience commentedon Nov 20, 2019
I presume it's because they're displaying the output stream in a different way. Like I said
-Transcriptalso works like-PassThrudoes for most cmdlets.Lets say there is a host application that displays output in a table, sorta like
Out-GridView. In order for it to do that it would need the objects returned as they are. Typically, when the host is told to write output lines, it's already been transformed into strings by the format engine. With this switch, it can write the output to the transcript as if it were a normal console, while still displaying the results how it wants to.In that scenario, the host is very unlikely to actually want a full
ErrorRecord, it's probably perfectly happy just writing that error message out in a box somewhere in the same format it would be written to the console.Well sorta. The example I gave would still work if you added
| Where-Object { $_ -isnot [ErrorRecord] }and etc for the other streams.Yeah probably. I don't think that parameter was meant to be used by anything other than hosts. In my opinion, it only makes sense for hosts because the intent is that the output is displayed some other way. A transcript is meant to be a recording of a session, purposefully avoiding that seems counter to the point of it to me. Are you trying to use transcripts for script logging?
Honestly I'd say throw
DontShowAttributeon it, assuming that my understanding of it's purpose is correct. If this parameter doesn't make sense for any consumer other than a host application, maybe it shouldn't show up in tab completion.mklement0 commentedon Nov 20, 2019
Yeah, the use case I inferred is definitely unusual, and arguably it's at odds with the idea of a transcript, as you indicate.
Note, however, that success output is silenced - which is what made me infer the silence-all-display-output-and-transcribe-only behavior.
Steve Lee (@SteveL-MSFT), can you or a subject-matter expert shed light on the purpose of
-Transcript?Is excluding it from tab completion and documenting it as not for use by end users the right way to go?
SeeminglyScience commentedon Nov 20, 2019
Yeah because that's the only stream it actually returns:
That's what makes the example I gave work. You take responsibility for displaying the output stream, but you still write to the transcript as if it were displayed normally.
SeeminglyScience commentedon Nov 20, 2019
Just to be perfectly clear though, I've never once used it nor have I ever even seen it used. I'm realizing my wording may have implied differently. This is all just what I'm inferring based on it's behavior of the switch and the design of transcripts.
BrucePay commentedon Nov 21, 2019
Some context: when we were designing the console host experience we realized that we had a problem. With split streams, displaying them individually (I.e. separated) meant that you wouldn't get errors in context which was bad for a console experience. To solve this we added a feature in the pipeline processor to merge the error output from all of the prior commands into the output stream. Then we created
Out-Defaultto take the merged output, demultiplex the records and render them appropriately. This cmdlet was really only intended to be used by the host. I assume (but don't know) since everything went throughOut-Defaultthis was the natural place to insert transcription.(Note: none of this applied to native commands in the terminal position in a pipeline. In that case, the subprocess received the console host io handles allowing them to write directly to a console. This was necessary so that things like
vim.execould work from PowerShell.exe. This also meant that output from native commands in this situation was not captured in the transcript.)mklement0 commentedon Nov 21, 2019
Taking a step back:
#11134 and this issue are ultimately (also) about asking the following questions:
Out-Defaultdirectly?And to then properly document the findings in the
Out-Defaulthelp topic: see MicrosoftDocs/PowerShell-Docs#5131It seems that (b) can be answered for parameter-less use of
Out-Default: do not use it as an end user - the primary reason it exists as a user-callable cmdlet is so you can override it with a custom implementation.Additionally, we need to establish whether it makes sense for end users to call
Out-Defaultwith-Transcript(its only cmdlet-specific parameter):I had inferred the purpose of
-Transcriptas allowing end users to write to the transcript only, without also printing to the host.Patrick Meinecke (@SeeminglyScience) provided an alternative explanation, which sounds more plausible to me: that
-Transcriptis really meant for use by application hosts; to quote him: "You take responsibility for displaying the output stream, but you still write to the transcript as if it were displayed normally."Therefore, Steve Lee (@SteveL-MSFT) and Bruce Payette (@BrucePay): Can you confirm that Patrick Meinecke (@SeeminglyScience)'s interpretation is correct or clarify the true purpose of
-Transcript, so we can guide users properly in the documentation?If we find that direct calls to
Out-Defaultnever make sense, we can close this issue; unfortunately, #11134 remains an issue either way, because it also affectsOut-Host, for which there are legitimate uses.Bruce Payette (@BrucePay)
It does apply to native commands in the context of transcribing, however, as evidenced by stderr output by default properly showing up in transcripts.
In other words: while transcribing, the direct-to-host behavior is intentionally disabled so as to be able to capture all output in the transcript.
Another way of demonstrating that is to start a transcript and then try to invoke
vim; what you'll see is the following warning (on macOS), followed by a blank line:(Type

:q<Enter>to exit Vim or buy).
As an aside: Note that after exiting Vim in this scenario the PSReadline bindings (arrow keys) don't work until you run
cls.SteveL-MSFT commentedon Nov 21, 2019
Michael Klement (@mklement0) the PSReadLine issue should be fixed in PSRL 2.0.0-beta6
From the source code:
mklement0 commentedon Nov 21, 2019
Thank you, Steve Lee (@SteveL-MSFT) - embarrassingly, it hadn't even occurred to me to look there.
So it sounds like Patrick Meinecke (@SeeminglyScience) was correct.
Regarding updating the
Out-Defaulthelp topic: Do you agree that we should therefore say:Out-Defaultis used internally and should not be called directly.The only reason it exists as a public cmdlet is so you can override it with a custom implementation.
SeeminglyScience commentedon Nov 21, 2019
I wouldn't use the term
internally. It's intended to be used by host applications. Said host applications do not have to be made internally for it's use to be considered supported.mklement0 commentedon Nov 21, 2019
Good point, Patrick Meinecke (@SeeminglyScience): How about:
SeeminglyScience commentedon Nov 22, 2019
Yeah something like that. Maybe borrow some wording from the remarks section of this:
PowerShell/src/System.Management.Automation/engine/MshMemberInfo.cs
Lines 1526 to 1533 in 8d944fd
mklement0 commentedon Nov 22, 2019
Thanks, Patrick Meinecke (@SeeminglyScience).
I've updated the suggested wording at MicrosoftDocs/PowerShell-Docs#5131, and I invite y'all to take a look.
Time to close this issue.