Make sure both stdout and stderr can be redirected from a native executable (#20997)

This commit is contained in:
Patrick Meinecke
2024-03-14 11:42:30 -07:00
committed by GitHub
parent d67a82d833
commit 4faf52726d
3 changed files with 44 additions and 30 deletions
@@ -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") {
+5
View File
@@ -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;