Powershell: Write-Error should use positional binding to -ErrorRecord and -Exception

Created on 8 Oct 2019  路  7Comments  路  Source: PowerShell/PowerShell

When using the parameter sets selected by -ErrorRecord / -Exception of Write-Error, it makes sense to bind (the first) _positional_ argument of types (derived from) System.Management.Automation.ErrorRecord / System.Exception to those parameters.

Currently, that doesn't happen, because these parameters lack the Position=0 attribute field in their `Parameter attributes.

The result is that using something like Write-Error $_ in an apparent effort to pass the System.Management.Automation.ErrorRecord instance in $_ through, you end up with the equivalent of:

Write-Error -Message $_

rather than the more sensible - and probably expected:

Write-Error -ErrorRecord $_

While the two resulting error records ultimately contain the same _message_ (description), the specifics of the input error record are lost.

The same applies analogously to -Exception.

The fix is trivial: Add Position = 0 to the following two locations:

https://github.com/PowerShell/PowerShell/blob/d2c04f3eef071b244838ba2dfa001dd4d5731843/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Write.cs#L235-L236

https://github.com/PowerShell/PowerShell/blob/d2c04f3eef071b244838ba2dfa001dd4d5731843/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Write.cs#L217-L218

Steps to reproduce

Run the following tests:

# ErrorRecord
try { [int]::parse('foo') } catch {}; (Write-Error $Error[0] 2>&1).Exception.GetType().FullName | Should -Be System.Management.Automation.MethodInvocationException

# Exception
try { [int]::parse('foo') } catch {}; (Write-Error $Error[0].Exception.InnerException 2>&1).Exception.GetType().FullName | Should -Be System.FormatException

# Make sure that a string still binds to -Message.
try { [int]::parse('foo') } catch {}; (Write-Error "$($Error[0])" 2>&1).Exception.GetType().FullName | Should -Be Microsoft.PowerShell.Commands.WriteErrorException

Expected behavior

All tests should pass.

Actual behavior

The first two tests fail, because the positional arguments bind to -Message, resulting in a generic Microsoft.PowerShell.Commands.WriteErrorException exception wrapper.

Environment data

PowerShell Core 7.0.0-preview.4
Area-Cmdlets-Utility Hacktoberfest Issue-Enhancement Up-for-Grabs

Most helpful comment

I'll work on this one.

All 7 comments

Does this interfere at all with binding Write-Error "message" positionally? I don't think it should, just want to confirm 馃檪

Good question, @vexx32 - yes, that still works; I've added tests to the OP to confirm that.

Excellent! This seems like a minor enhancement-type change. Marking it for Hacktoberfest. 馃榿

I'll work on this one.

@tnieto88 are you still interested in putting this one together? 馃槉

@vexx32 yeah I am, would this change require new tests to be added?

Ideally yes. You can reuse the rest code @mklement0 has in the issue description and just have those three cases written up as individual tests in the Write-Error tests file. :blush:

Was this page helpful?
0 / 5 - 0 ratings