Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ static ExperimentalFeature()
new ExperimentalFeature(
name: "PSNativePSPathResolution",
description: "Convert PSPath to filesystem path, if possible, for native commands"),
new ExperimentalFeature(
name: "PSNotApplyErrorActionToStderr",
description: "Don't have $ErrorActionPreference affect stderr output"),
};
EngineExperimentalFeatures = new ReadOnlyCollection<ExperimentalFeature>(engineFeatures);

Expand Down
95 changes: 48 additions & 47 deletions src/System.Management.Automation/engine/MshCommandRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2831,61 +2831,62 @@ internal void _WriteErrorSkipAllowCheck(ErrorRecord errorRecord, ActionPreferenc
this.PipelineProcessor.LogExecutionError(_thisCommand.MyInvocation, errorRecord);
}

ActionPreference preference = ErrorAction;
if (actionPreference.HasValue)
if (!(ExperimentalFeature.IsEnabled("PSNotApplyErrorActionToStderr") && isNativeError))
{
preference = actionPreference.Value;
}
ActionPreference preference = ErrorAction;
if (actionPreference.HasValue)
{
preference = actionPreference.Value;
}

// No trace of the error in the 'Ignore' case
if (ActionPreference.Ignore == preference)
{
return; // do not write or record to output pipe
}
// No trace of the error in the 'Ignore' case
if (ActionPreference.Ignore == preference)
{
return; // do not write or record to output pipe
}

// 2004/05/26-JonN
// The object is not written in the SilentlyContinue case
if (ActionPreference.SilentlyContinue == preference)
{
AppendErrorToVariables(errorRecord);
return; // do not write to output pipe
}
// 2004/05/26-JonN
// The object is not written in the SilentlyContinue case
if (ActionPreference.SilentlyContinue == preference)
{
AppendErrorToVariables(errorRecord);
return; // do not write to output pipe
}

if (ContinueStatus.YesToAll == lastErrorContinueStatus)
{
preference = ActionPreference.Continue;
}
if (ContinueStatus.YesToAll == lastErrorContinueStatus)
{
preference = ActionPreference.Continue;
}

switch (preference)
{
case ActionPreference.Stop:
ActionPreferenceStopException e =
new ActionPreferenceStopException(
MyInvocation,
errorRecord,
StringUtil.Format(CommandBaseStrings.ErrorPreferenceStop,
"ErrorActionPreference",
errorRecord.ToString()));
throw ManageException(e);
switch (preference)
{
case ActionPreference.Stop:
ActionPreferenceStopException e =
new ActionPreferenceStopException(
MyInvocation,
errorRecord,
StringUtil.Format(CommandBaseStrings.ErrorPreferenceStop,
"ErrorActionPreference",
errorRecord.ToString()));
throw ManageException(e);

case ActionPreference.Inquire:
// ignore return value
// this will throw if the user chooses not to continue
lastErrorContinueStatus = InquireHelper(
RuntimeException.RetrieveMessage(errorRecord),
null,
true, // allowYesToAll
false, // allowNoToAll
true, // replaceNoWithHalt
false // hasSecurityImpact
);
break;
}

case ActionPreference.Inquire:
// ignore return value
// this will throw if the user chooses not to continue
lastErrorContinueStatus = InquireHelper(
RuntimeException.RetrieveMessage(errorRecord),
null,
true, // allowYesToAll
false, // allowNoToAll
true, // replaceNoWithHalt
false // hasSecurityImpact
);
break;
AppendErrorToVariables(errorRecord);
}

// 2005/01/20 Do not write the object to $error if
// ManageException has already done so
AppendErrorToVariables(errorRecord);

// Add this note property and set its value to true for F&O
// to decide whether to call WriteErrorLine or WriteLine.
// We want errors to print in red in both cases.
Expand Down
13 changes: 0 additions & 13 deletions test/powershell/Host/ConsoleHost.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,6 @@ Describe "ConsoleHost unit tests" -tags "Feature" {
{ & $powershell -outp blah -comm { $input } } | Should -Throw -ErrorId "IncorrectValueForFormatParameter"
}

It "Verify Validate Dollar Error Populated should throw exception" {
$origEA = $ErrorActionPreference
$ErrorActionPreference = "Stop"
$a = 1,2,3
$e = {
$a | & $powershell -noprofile -command { wgwg-wrwrhqwrhrh35h3h3}
} | Should -Throw -ErrorId "CommandNotFoundException" -PassThru

$e.ToString() | Should -Match "wgwg-wrwrhqwrhrh35h3h3"

$ErrorActionPreference = $origEA
}

It "Verify Validate Output Format As Text Explicitly Child Single Shell does not throw" {
{
"blahblah" | & $powershell -noprofile -out text -com { $input }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ Describe "Native Command Processor" -tags "Feature" {
[Console]::OutputEncoding = $originalOutputEncoding
}
}

It '$ErrorActionPreference does not apply to redirected stderr output' -Skip:(!$EnabledExperimentalFeatures.Contains('PSNotApplyErrorActionToStderr')) {
pwsh -noprofile -command '$ErrorActionPreference = ''Stop''; testexe -stderr stop 2>$null; ''hello''; $error' | Should -BeExactly 'hello'
}
}

Describe "Open a text file with NativeCommandProcessor" -tags @("Feature", "RequireAdminOnWindows") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ Describe "Native streams behavior with PowerShell" -Tags 'CI' {

# this check should be the first one, because $error is a global shared variable
It 'should not add records to $error variable' {
# we are keeping existing Windows PS v5.1 behavior for $error variable
$error.Count | Should -Be 9
$error.Count | Should -Be 0
}

It 'uses ErrorRecord object to return stderr output' {
Expand Down
3 changes: 3 additions & 0 deletions test/tools/TestExe/TestExe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ static int Main(string[] args)
// Used to test functionality depending on $LASTEXITCODE, like &&/|| operators
Console.WriteLine(args[1]);
return int.Parse(args[1]);
case "-stderr":
Console.Error.WriteLine(args[1]);
break;
default:
Console.WriteLine("Unknown test {0}", args[0]);
break;
Expand Down