Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remoting infrastructure doesn't allow capturing / redirection of any streams other than success and error #9585

Open
mklement0 opened this issue May 13, 2019 · 12 comments

Comments

Projects
None yet
4 participants
@mklement0
Copy link
Contributor

commented May 13, 2019

When using the PowerShell remoting infrastructure, which includes:

  • true remoting:
    • Invoke-Command
    • implicit remoting with Import-PSSession
  • background jobs:
    • Start-Job
    • postpositional &
  • calling the CLI:
    • from within PowerShell with -Command and a script block

the only output streams that can be captured / redirected are 1 (success) and 2 (error) - all others seemingly print straight to the console.

Update: @PetSerAl notes that the information stream can be redirected, but invariably also prints to the screen, which cannot be suppressed - see #7814

Steps to reproduce

# Write to all output streams from a background job 
# and try to suppress them all when receiving the job's output.
$null = & { 1; write-error 2; write-warning 3; write-verbose -vb 4; write-debug -debug 5; write-information -InformationAction Continue 6 } &
($job = Get-Job) |  Receive-Job -wait  *>$null

As @Niali points out in #5848 (comment), the streams' contents are accessible via the job object, curiously via the .Output, .Error, ... properties of $job.ChildJob[0](!).

Update: @PetSerAl notes that -WarningVariable on the -Receive-Job call can be used to capture the warning stream - and so can the information stream with -InformationVariable , though they still also print to the screen, which cannot be suppressed.

Expected behavior

No output.

Actual behavior

The following output:

WARNING: 3
VERBOSE: 4
DEBUG: 5
6

Environment data

PowerShell Core 6.2.0
@PetSerAl

This comment has been minimized.

Copy link
Contributor

commented May 19, 2019

Information stream also can be redirected. If you put $InformationPreference = 'Continue' outside and remove redirection, then you will see that information record get printed twice. Also note that warning stream still will be putted to -WarningVariable of Receive-Job.

@mklement0

This comment has been minimized.

Copy link
Contributor Author

commented May 21, 2019

Thanks, @PetSerAl, I've updated the OP accordingly. So this means that while you can capture the information stream with a redirection and with-InformationVariable, and the warning stream with -WarningVariable only, the streams (effectively) still also print to the console, which cannot be suppressed.

@PetSerAl

This comment has been minimized.

Copy link
Contributor

commented May 21, 2019

What you are seeing on console is actually a host stream. Warning/verbose/debug/information records processed remotely and resulting writes to host transferred and replicated locally.

@mklement0

This comment has been minimized.

Copy link
Contributor Author

commented May 21, 2019

Thanks, @PetSerAl; so, to summarize:

When remoting:

  • streams 3, 4, 5, 6 cannot be suppressed, because they are locally replicated as host output, which is invariably printed.
  • of these, only stream 6 can be redirected to a file, and both 3 and 6 can be captured with a -*Variable parameter; 4, 5 can neither be redirected nor captured (they have no -*Variable parameter).

Is this a fair summary, and do you agree that there's a problem?

@PetSerAl

This comment has been minimized.

Copy link
Contributor

commented May 25, 2019

It is depend on how you define "problem". There are many things I wish was implemented differently in PowerShell, but them are not and would not. Given the amount of hoops PowerShell jump thru to implement this particular behavior, I presume it intentionally done this way for compatibility reasons, thus unlikely be changed given possibility of cross-version remoting.

@mklement0

This comment has been minimized.

Copy link
Contributor Author

commented May 25, 2019

@PetSerAl

There are many things I wish was implemented differently in PowerShell, but them are not and would not.

That's the subject of #6745, and even if changing something isn't an option for the sake of preserving backward compatibility, it is always worth getting clarity on how things should work.

That said, the behavior at hand strikes me as benefitting no one, so I don't even see a reason to hang on to it for the sake of backward compatibility.

As for defining "problem": In this context, it is Inconsistent, obscure behavior that prevents expected functionality.

@PetSerAl

This comment has been minimized.

Copy link
Contributor

commented May 25, 2019

@mklement0 So, can you propose less inconsistent, less obscure and more expected behavior?

@mklement0

This comment has been minimized.

Copy link
Contributor Author

commented May 25, 2019

I can describe the desired behavior, but I can't speak to the technical challenges or feasibility:

Map all remote streams to the local ones fully transparently, so that the following features work the same, whether remoting is involved or not:

  • redirection to a file
  • host-output suppression (redirection to $null; redirected-to-a-file output not also printing to the host)
  • use of the common -*Variable parameters

Isn't that the obvious expectation?

@PetSerAl

This comment has been minimized.

Copy link
Contributor

commented May 25, 2019

Invoke-Command -ComputerName SomeName {
    Write-Verbose Remote -Verbose
}

Should this command display verbose message?

Invoke-Command {
    Write-Verbose Local -Verbose
}

How about this one?

@vexx32

This comment has been minimized.

Copy link
Contributor

commented May 25, 2019

Both of them should. However, if you redirect that stream, it should not show.

Invoke-Command -ComputerName SomeName {
    Write-Verbose Remote -Verbose
} 4> $null # should suppress verbose
@PetSerAl

This comment has been minimized.

Copy link
Contributor

commented May 25, 2019

@vexx32

Both of them should.

But when Invoke-Command produce verbose message locally, it should be governed by local $VerbosePreference, which is SilentlyContinue by default, thus verbose message should be suppressed.

@mklement0

This comment has been minimized.

Copy link
Contributor Author

commented May 25, 2019

@PetSerAl

That applies to the verbose messages the Invoke-Command itself emits, not to whatever the script block it happens to be passed does.

In fact, your local example behaves exactly as expected already. Now we just need to make sure the remote behavior matches.

Also note that there are remoting scenarios where the user may not even be aware that remoting is involved: implicit remoting, calling the CLI from within PowerShell with a script block. Having such commands behave differently with respect to output streams is, as stated, inconsistent and obscure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.