mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Make sure both stdout and stderr can be redirected from a native executable (#20997)
This commit is contained in:
@@ -814,12 +814,6 @@ namespace System.Management.Automation
|
||||
{
|
||||
if (blocking)
|
||||
{
|
||||
if (_stdOutByteTransfer is not null)
|
||||
{
|
||||
_stdOutByteTransfer.EOF.GetAwaiter().GetResult();
|
||||
return null;
|
||||
}
|
||||
|
||||
// If adding was completed and collection is empty (IsCompleted == true)
|
||||
// there is no need to do a blocking Take(), we should just return.
|
||||
if (!_nativeProcessOutputQueue.IsCompleted)
|
||||
@@ -841,17 +835,9 @@ namespace System.Management.Automation
|
||||
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_stdOutByteTransfer is not null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ProcessOutputObject record = null;
|
||||
_nativeProcessOutputQueue.TryTake(out record);
|
||||
return record;
|
||||
}
|
||||
_nativeProcessOutputQueue.TryTake(out ProcessOutputObject record);
|
||||
return record;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -859,21 +845,38 @@ namespace System.Management.Automation
|
||||
/// </summary>
|
||||
private void ConsumeAvailableNativeProcessOutput(bool blocking)
|
||||
{
|
||||
if (!_isRunningInBackground)
|
||||
if (_isRunningInBackground)
|
||||
{
|
||||
if (_nativeProcess.StartInfo.RedirectStandardOutput || _nativeProcess.StartInfo.RedirectStandardError)
|
||||
{
|
||||
ProcessOutputObject record;
|
||||
while ((record = DequeueProcessOutput(blocking)) != null)
|
||||
{
|
||||
if (this.Command.Context.CurrentPipelineStopping)
|
||||
{
|
||||
this.StopProcessing();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessOutputRecord(record);
|
||||
bool stdOutRedirected = _nativeProcess.StartInfo.RedirectStandardOutput;
|
||||
bool stdErrRedirected = _nativeProcess.StartInfo.RedirectStandardError;
|
||||
if (stdOutRedirected && _stdOutByteTransfer is not null)
|
||||
{
|
||||
if (blocking)
|
||||
{
|
||||
_stdOutByteTransfer.EOF.GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
if (!stdErrRedirected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (stdOutRedirected || stdErrRedirected)
|
||||
{
|
||||
ProcessOutputObject record;
|
||||
while ((record = DequeueProcessOutput(blocking)) != null)
|
||||
{
|
||||
if (this.Command.Context.CurrentPipelineStopping)
|
||||
{
|
||||
this.StopProcessing();
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessOutputRecord(record);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -886,7 +889,7 @@ namespace System.Management.Automation
|
||||
if (!_isRunningInBackground)
|
||||
{
|
||||
// Wait for input writer to finish.
|
||||
if (!UpstreamIsNativeCommand)
|
||||
if (!UpstreamIsNativeCommand || _nativeProcess.StartInfo.RedirectStandardError)
|
||||
{
|
||||
_inputWriter.Done();
|
||||
}
|
||||
@@ -1771,7 +1774,7 @@ namespace System.Management.Automation
|
||||
|
||||
// we incrementing refCount on the same thread and before running any processing
|
||||
// so it's safe to do it without Interlocked.
|
||||
if (process.StartInfo.RedirectStandardOutput)
|
||||
if (process.StartInfo.RedirectStandardOutput && stdOutDestination is null)
|
||||
{
|
||||
_refCount++;
|
||||
}
|
||||
|
||||
@@ -213,6 +213,12 @@ Describe "Native Command Processor" -tags "Feature" {
|
||||
Wait-UntilTrue -sb { (Get-Process mmc).Count -gt 0 } -TimeoutInMilliseconds 5000 -IntervalInMilliseconds 1000 | Should -BeTrue
|
||||
Get-Process mmc | Stop-Process
|
||||
}
|
||||
|
||||
It 'Can redirect stdout and stderr to different files' {
|
||||
testexe -stderrandout testing > $TestDrive/stdout.txt 2> $TestDrive/stderr.txt
|
||||
Get-Content $TestDrive/stdout.txt | Should -Be testing
|
||||
Get-Content $TestDrive/stderr.txt | Should -Be gnitset
|
||||
}
|
||||
}
|
||||
|
||||
Describe "Open a text file with NativeCommandProcessor" -tags @("Feature", "RequireAdminOnWindows") {
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.IO;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace TestExe
|
||||
{
|
||||
@@ -36,6 +37,10 @@ namespace TestExe
|
||||
case "-stderr":
|
||||
Console.Error.WriteLine(args[1]);
|
||||
break;
|
||||
case "-stderrandout":
|
||||
Console.WriteLine(args[1]);
|
||||
Console.Error.WriteLine(new string(args[1].ToCharArray().Reverse().ToArray()));
|
||||
break;
|
||||
case "-readbytes":
|
||||
ReadBytes();
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user