Skip to content

S.M.A.PowerShell.HadErrors and $? return false positives when errors are suppressed #4613

@KirkMunro

Description

@KirkMunro

Created from discussion started on #3768.

Description

If you invoke PowerShell using the System.Management.Automation.PowerShell class, and if you handle the errors in the command you invoke by indicating that they should be ignored, S.M.A.PowerShell will still set HadErrors to true. Below are some code samples illustrating the problem.

Sample 1: C#/.NET invocation of PowerShell commands/scripts

$ps = [PowerShell]::Create()
$ps.AddCommand('Get-Service').AddParameter('Name','Invalid').AddParameter('ErrorAction',[System.Management.Automation.ActionPreference]::Ignore) > $null
$ps.Invoke()
$ps.HadErrors # returns $true; expectation is that this would return false since the command was configured to ignore errors

Sample 1: Expected behavior

$ps.HadErrors should return $false

Sample 1: Actual behavior

$ps.HadErrors returns $true, even when $ps.Streams.Error does not contain any errors (because there were no errors!)

Sample 2: Direct command invocation in PowerShell

Get-Service -Name Invalid -ErrorAction Ignore
$? # returns $false; shouldn't this return $true?

Sample 2: Expected behavior

$? should return $true

Sample 2: Actual behavior

$? returns $false, even though there were no errors because the invoker of the command instructed PowerShell to ignore the error that would otherwise have been raised because it is a benign error for them (and therefore, not an error)

Additional Details

In both of these cases, -ErrorAction Ignore is being used to tell PowerShell that the error is actually not an error as far as this invocation is concerned, and therefore it can be completely ignored. Why then, do both $? and $ps.HadErrors indicate there was still error? Technically there was an error, by definition of the command being invoked, but it is being handled/treated like it is not an error in the command from which the command producing the error was invoked. In both of these cases $? and $ps.HadErrors should have values indicating that there wasn't an error. If you do not trust the command you are invoking to ignore benign errors and only notify you about errors that you actually need to care about then you should not be invoking that command.

Environment data

PS C:\> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      6.0.0-beta
PSEdition                      Core
GitCommitId                    v6.0.0-beta.5
OS                             Microsoft Windows 10.0.16251
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    Breaking-Changebreaking change that may affect usersCommittee-ReviewedPS-Committee has reviewed this and made a decisionIssue-Discussionthe issue may not have a clear classification yet. The issue may generate an RFC or may be reclassifResolution-No ActivityIssue has had no activity for 6 months or moreWG-Enginecore PowerShell engine, interpreter, and runtime

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions