Currently Write-Error has many parameters to create a rich ErrorRecord and write it to the error channel as a non-terminating error.
Throw allows us to generate a terminating error and provide a string for the exception message, or an ErrorRecord object to pass, but without getting into New-Object territory there is no easy way to create an error record and pass to Throw.
New-ErrorRecord would allow us to generate the error details and then choose to write or throw it as necessary.
See https://gist.github.com/wpsmith/e8a9c54ca1c7c741b5e9 as an example Cmdlet.
See also this search for 1683 examples of this pattern:
https://github.com/search?utf8=%E2%9C%93&q=%22New-Object+System.Management.Automation.ErrorRecord%22+language%3APowerShell&type=Code&ref=searchresults
Is there a good reason to not prefer an improved api?
I'd imagine this is annoying for authors of C# cmdlets as well.
Can we use
$a=Write-Error -Message "eee" 2>&1
instead of New-ErrorRecord?
@iSazonov that's a clever way to achieve the same result, but I don't think everyone should need to be that clever to create an error record for throwing.
Maybe we just add such feature in Write-Error ? New parameter?
A new parameter on Write-Error is still not obvious, and still doesn't help C# authors.
I'd start with a new api - and if that's still not sufficient, only then would I consider a new cmdlet.
@lzybkr Can you help me understand as someone without background in C# what the experience would be in Powershell for interacting with a new API? I'm not sure what that would mean in this context. I'm happy for any solution that makes it easier to generate detailed terminating/non-terminating errors.
Is the objection to needing New-Object? Or the need for multiple invocations to New-Object?
It's already fine to throw an ErrorRecord today even though it is not an Exception.
I was thinking there could be another constructor to ErrorRecord with a signature similar to the New-ErrorRecord script you linked to, so you'd use something like:
$err = [ErrorRecord]::new([InvalidOperationException], $message, $errorId, $errorCategory, $targetObj)
It's definitely useful to be able to make a new error record with an exception in a single line, but I'm pretty sure that it would be enough if there was just a -AsTerminatingException switch on Write-Error ;-)
@Jaykul Personally I am fine with that solution. I think that covers 95% of the use cases, I just wasn't sure if throwing a terminating error was kosher for a "Write" verb.
Maybe -Throw more clear for users?
It is not exclude New-ErrorRecord for more complex cases (5%).
Let me try to summarize and make a suggestion:
In _PowerShell code_, Write-Error, via its -Category, -ErrorId, ... parameters, already offers a way to create custom ErrorRecord instances, by either wrapping a _custom error message_ (-Message) or a _preexisting exception_ (-Exception) - though the latter is currently broken - see #10774.
However, creating such a custom ErrorRecord is currently tied solely to writing directly to the error stream, i.e. limited to creating a _non-terminating_ error.
Introducing something like a -AsTerminatingError switch as suggested by @Jaykul (or @iSazonov's simpler alternative name, -Throw, which I like for its association with the Throw statement) would remove this limitation, to allow the custom error record to be thrown as a script-terminating (runspace-terminating) error as well, like a customized Throw call.
$PSCmdlet.ThrowTerminatingError directly, which scripters should not be expected to need to use); conversely, (binary) cmdlets _cannot_ raise script-terminating errors themselves and can only create _statement_-terminating ones, via Cmdlet.ThrowTerminatingError() or by throwing or not catching a raw exception.Someone who really wants to create a custom ErrorRecord _in isolation_, for later use - which is clearly an advanced use case - can use New-Object System.Management.Automation.ErrorRecord or [System.Management.Automation.ErrorRecord]::new() directly, as needed.
_Separately_, in parallel, _for SDK users_ (in C#) , providing a more convenient way to construct custom ErrorRecords implicitly, via arguments passed to new Cmdlet.WriteError() / Cmdlet.ThrowTerminatingError() overloads, as suggested by @lzybkr, is well worth considering.
One point I'd like to mention is that Write-Error _does_ in fact support creating terminating errors, via -ErrorAction Stop if I'm not mistaken. 馃檪
The rest sounds good!
Thanks, @vexx32. -ErrorAction Stop does work, but is suboptimal in that it creates an _extra_ entry in $Error: a System.Management.Automation.ActionPreferenceStopException exception with message
The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop
Write-Error also doesn't provide access to all the properties of ErrorRecord. Consider ScriptStackTrace for example.
Most helpful comment
Let me try to summarize and make a suggestion:
In _PowerShell code_,
Write-Error, via its-Category,-ErrorId, ... parameters, already offers a way to create customErrorRecordinstances, by either wrapping a _custom error message_ (-Message) or a _preexisting exception_ (-Exception) - though the latter is currently broken - see #10774.However, creating such a custom
ErrorRecordis currently tied solely to writing directly to the error stream, i.e. limited to creating a _non-terminating_ error.Introducing something like a
-AsTerminatingErrorswitch as suggested by @Jaykul (or @iSazonov's simpler alternative name,-Throw, which I like for its association with theThrowstatement) would remove this limitation, to allow the custom error record to be thrown as a script-terminating (runspace-terminating) error as well, like a customizedThrowcall.$PSCmdlet.ThrowTerminatingErrordirectly, which scripters should not be expected to need to use); conversely, (binary) cmdlets _cannot_ raise script-terminating errors themselves and can only create _statement_-terminating ones, viaCmdlet.ThrowTerminatingError()or by throwing or not catching a raw exception.Someone who really wants to create a custom
ErrorRecord_in isolation_, for later use - which is clearly an advanced use case - can useNew-Object System.Management.Automation.ErrorRecordor[System.Management.Automation.ErrorRecord]::new()directly, as needed._Separately_, in parallel, _for SDK users_ (in C#) , providing a more convenient way to construct custom
ErrorRecords implicitly, via arguments passed to newCmdlet.WriteError()/Cmdlet.ThrowTerminatingError()overloads, as suggested by @lzybkr, is well worth considering.