Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I display a 'naked' error message in PowerShell without an accompanying stacktrace?

How can I write to standard error from PowerShell, or trap errors such that:

  • An error message is displayed as an error (truly writing to standard error so that TeamCity and Octopus see it as an error)
  • No stack trace garbage muddles my beautiful, concise error message

All these years I've survived by throwing errors or writing via Write-Error, but I'm tired and old, and in my scripts I just want to see one concise error message. I've been trying every combination of trap, throw, Write-Error, and -ErrorAction, to no avail:

try {   throw "error" # Sample code for a stack overflow. In the theater   # of your mind, imagine there is code here that does something real and useful } catch {   Write-Error "An error occurred attempting to 'do something.' Have you tried rebooting?" } 

Here's the user experience I want to see:

C:\> & .\Do-Something.ps1 An error occurred attempting to 'do something.' Have you tried rebooting?  C:\> ▏ 

Instead I get:

C:\> & .\Do-Something.ps1 An error occurred attempting to 'do something.' Have you tried rebooting? At line:1 char:1 + Do-RealWork + ~~~~~~~~~~~~~~~~~~~     + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException     + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Do-RealWork  C:\> ▏ 
like image 912
Peter Seale Avatar asked Jun 27 '16 23:06

Peter Seale


People also ask

How do you show error messages in PowerShell?

You can use Get-Error to display a specified number of errors that have occurred in the current session using the Newest parameter. The Get-Error cmdlet also receives error objects from a collection, such as $Error , to display multiple errors from the current session.

How do I ignore exceptions in PowerShell?

If there are special commands you want to ignore you can use -erroraction 'silentlycontinue' which will basically ignore all error messages generated by that command. You can also use the Ignore value (in PowerShell 3+): Unlike SilentlyContinue, Ignore does not add the error message to the $Error automatic variable.

How do I hide errors in PowerShell?

If you need to suppress an error, you can use the ErrorAction switch to suppress an error for a single cmdlet or an ErrorAction preference variable to suppress errors globally.

How do you handle exceptions in PowerShell?

A better way to handle this exception is to convert the non-terminating error to the terminating one using the ErrorAction parameter or $ErrorActionPreference variable. By default, the value for this variable is set to the Continue by PowerShell so in the case of error, the program continues.


1 Answers

Setting the automatic $ErrorView variable to 'CategoryView' causes PowerShell to output concise, single-line error representations instead, but this representation may not always include enough information, because the error message is typically not included; on the plus side, the text passed to Throw "..." is reflected, but, by contrast, Write-Error output contains no specific information while 'CategoryView' is in effect.
Adding a new error view to PowerShell that is single-line yet always contains all crucial information is being discussed for v6.

Provided that your PowerShell code is run from a console (uses a console host), use [Console]::Error.WriteLine(), which unconditionally writes to the outside world's stderr (standard error stream):

[Console]::Error.WriteLine("An error occurred ... Have you tried rebooting?") 

Note:

  • This won't work from non-console hosts such as the PowerShell ISE.

  • [Console]::Error.WriteLine() output doesn't print in red in the console [1].


Sadly, there is no single solution that works both from within PowerShell (across hosts) and from outside of it:

  • [Console]::Error.WriteLine(), while writing properly to stderr for the outside world, cannot have its output captured or suppressed inside PowerShell, and only works with the PowerShell console host.

  • Similarly, $host.ui.WriteErrorLine(), even though works with all hosts, it is a UI method that works outside PowerShell's stream system as well and therefore its output too cannot be captured or suppressed in PowerShell.
    More importantly, it doesn't write to the outside world's stderr (it behaves like Write-Error in this respect, see below).

  • Inside PowerShell, only Write-Error writes to PowerShell's error stream, so its output can be captured / suppressed.
    However, unfortunately, Write-Error (apart from being noisy) does not write to the outside world's stderr, unless, bizarrely, stderr is explicitly being redirected - see this answer of mine for details.


[1] Peter (the OP himself) offers a workaround for that:

[Console]::ForegroundColor = 'red' [Console]::Error.WriteLine("An error occurred ... Have you tried rebooting?") [Console]::ResetColor() 

suneg's helpful answer provides a function wrapper for it.

Fortunately, PowerShell automatically omits the color codes when it detects that the output is being redirected (to a file).

like image 150
mklement0 Avatar answered Sep 20 '22 21:09

mklement0