Powershell: Warning, Verbose, and Debug cannot be redirected to another stream, file, or variable when coming from a remote source

Created on 1 Sep 2020  路  8Comments  路  Source: PowerShell/PowerShell

This is in reference to issue #5063, which was closed same-day it was opened as unable-to-reproduce, though it is reliably reproducible. Hopefully, my explanation will be easier to reproduce and more complete, and might actually lead to this long-standing issue that I suspect has been present since data streams number 3, 4, and 5 were first introduced.

Longer explanation:
When the source of data streams is not the local machine, such as from Invoke-Command or a remote session such as Exchange uses, stream redirection for streams 3, 4, and 5 (Warning, Verbose, and Debug, respectively) do not work. Streams 1, 2, and 6 (Success/StOut, Error/StdErr, and Information, respectively) behave as expected. Since 3, 4, and 5 were all introduced in version 3.0, 1 and 2 introduced in 2.0, and 6 in 5.0, I suspect the issue was introduced with those streams.

I've replicated this issue in both 5.1 and 7.0 (specifically 7.0.2 and 7.0.3), originating from Server 2016 and Server 2019, targeting Server 2016 and 2019 as well as Windows 10 1909.

Steps to reproduce

Invoke-Command -ScriptBlock {Write-Warning 'test'} -ComputerName <remotehost> 3> test.txt
Get-Content -Path test.txt

Expected behavior

PS> Invoke-Command -ScriptBlock {Write-Warning 'test'} -ComputerName comp1 3> test.txt
PS> Get-Content -Path test.txt
test
PS>

Actual behavior

PS> Invoke-Command -ScriptBlock {Write-Warning 'test'} -ComputerName comp1 3> test.txt
WARNING: test
PS> Get-Content -Path test.txt
PS>

Environment data

Provided from one of the source systems (Server 2019)

Name                           Value
----                           -----
PSVersion                      7.0.3
PSEdition                      Core
GitCommitId                    7.0.3
OS                             Microsoft Windows 10.0.17763
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

Most helpful comment

Good find, @poshcodebear, but the relevant issue - which is still open - is #9585, which has quite a bit of debate already.

Yeah, in all my looking I didn't run into that one or I would have simply commented these details there. That said, that debate looks like it's been swept under the rug, left open but ignored for over a year, and the last comment seems to continue to miss the point that the stream pipelines are not behaving as expected through the remote infrastructure.

At this point, this feels like it's going to not be fixed under the dubious reasoning of "backward compatibility", though nothing really deals with direct console host writes other than the console host itself, which doesn't care if it comes directly or through a pipeline, and the pipeline streams we're discussing are already expecting to receive this kind of data, I don't see what the problem is. This seems like a legacy holdover akin to the old Write-Host, except we were actually willing to _fix_ Write-Host. That data no longer writes straight to the host, and fixing that required creating a whole new stream (which, as noted before, appears to receive remote output as expected). All I'm looking for here is for the streams in question to _actually receive data from their remote counterparts the same way Success, Error, and Information already do_.

Writing directly to the console host and bypassing all data streams should not still be happening.

All 8 comments

Note: the above test also works with Write-Verbose ... -Verbose and 4> to redirect, and Write-Debug ... -Debug and 5> to redirect. It also prevents those streams from being captured by a running transcript.

Additionally, -WarningVariable does not work, though -WarningAction does properly alter whether or not the host displays the warning.

Out of curiosity, does it work if you wrap the invoke-command call in parentheses? I.e., (Invoke-Command ...) 4>&1 or similar?

Out of curiosity, does it work if you wrap the invoke-command call in parentheses? I.e., (Invoke-Command ...) 4>&1 or similar?

Same result

Thought it would, just wanted to make sure.

/cc @PaulHigin

I think we may have had some similar issues in the past, but I'm not sure if I can find them at the moment...

This is a consequence of how remote data streams are written directly to the client host via remote host callbacks. I don't remember why it was written this way, but I recall issues with getting duplicate messages in the console. It can be changed but we would have to decide how Invoke-Command, Start-Job should handle these data streams. It would be a breaking change.

Good find, @poshcodebear, but the relevant issue - which is still open - is #9585, which has quite a bit of debate already.

This is a consequence of how remote data streams are written directly to the client host via remote host callbacks. I don't remember why it was written this way, but I recall issues with getting duplicate messages in the console. It can be changed but we would have to decide how Invoke-Command, Start-Job should handle these data streams. It would be a breaking change.

If it's a breaking change, it's a breaking change to make the shell behave in a consistent way. Additionally, I'm struggling to understand how the expectation of writing directly to the host for those streams instead of the corresponding local stream pipelines even makes sense, let alone is part of an expectation for existing code. Currently, it looks like nothing is going into those stream pipelines from remote and the output is completely invisible to the pipeline at this point, much like the old behavior of Write-Host. We threw out Write-Host entirely and built an entirely new output stream to take its place so it would behave in an expected manner.

If someone wrote a script that is expecting to act on these streams and suddenly gets more information than it did prior to fixing this, what would actually be the result of it? Most likely anything that's to be done with those streams is an attempt to capture them for logging or review purposes.

Currently, these streams may as well not exist if they're coming from a remote session; unless someone's sitting at the console that it writes to, the data will be lost, and there's nothing anyone can really do about it.

I mean, I suppose I could redirect the output to a different stream that does get remoted correctly to a local stream while it's on the remote system, but I won't be able to tell which stream it's coming from, and that doesn't help with commands going through remote endpoints (such as Exchange cmdlets).

Good find, @poshcodebear, but the relevant issue - which is still open - is #9585, which has quite a bit of debate already.

Yeah, in all my looking I didn't run into that one or I would have simply commented these details there. That said, that debate looks like it's been swept under the rug, left open but ignored for over a year, and the last comment seems to continue to miss the point that the stream pipelines are not behaving as expected through the remote infrastructure.

At this point, this feels like it's going to not be fixed under the dubious reasoning of "backward compatibility", though nothing really deals with direct console host writes other than the console host itself, which doesn't care if it comes directly or through a pipeline, and the pipeline streams we're discussing are already expecting to receive this kind of data, I don't see what the problem is. This seems like a legacy holdover akin to the old Write-Host, except we were actually willing to _fix_ Write-Host. That data no longer writes straight to the host, and fixing that required creating a whole new stream (which, as noted before, appears to receive remote output as expected). All I'm looking for here is for the streams in question to _actually receive data from their remote counterparts the same way Success, Error, and Information already do_.

Writing directly to the console host and bypassing all data streams should not still be happening.

Was this page helpful?
0 / 5 - 0 ratings