16

Why isn't Powershell's Write-Error cmdlet working for me? My output doesn't look like the examples in the documentation:

PS C:\> Write-Error "This is an error"
Write-Error "This is an error" : This is an error
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException

I had been expecting output similar to Write-Warning:

PS H:\> Write-Warning "This is a warning"
WARNING: This is a warning

From the Write-Error and about_preference_variables documentation I thought I should not see any exceptions?

PS H:\> Get-Help About_Preference_Variables

$ErrorActionPreference
----------------------

...

        PS> $erroractionpreference                      
        Continue        # Display the value of the preference.                

        PS> write-error "Hello, World"                  
                                # Generate a non-terminating error.

        write-error "Hello, World" : Hello, World       
                                # The error message is displayed and
                                  execution continues.

        PS> write-error "Hello, World" -ErrorAction:SilentlyContinue
                                # Use the ErrorAction parameter with a 
                                  value of "SilentlyContinue".
        PS>                                             
                                # The error message is not displayed and
                                  execution continues.
sourcenouveau
  • 29,356
  • 35
  • 146
  • 243

4 Answers4

17

To get output similar to write-warning, you can do this:

$Host.UI.WriteErrorLine("This is an error")

(props to Chris Sears for this answer)

Neil
  • 7,227
  • 5
  • 42
  • 43
  • Great! This is definitely useful for me. – sourcenouveau Apr 13 '11 at 23:53
  • 2
    Interestingly, this writes to stdout, not stderr. PowerShell ISE appears not echo stderr, though the normal PowerShell prompt does (with no special formatting applied). Try running `[System.Console]::Error.WriteLine('test')` in each and see what happens. – Zenexer Jul 19 '13 at 10:39
  • 4
    Don't do this. `WriteErrorLine` is a UI method, which is why as Zenexer says nothing is redirected to stderr. See Keith Hill's answer and http://stackoverflow.com/questions/4998173/how-do-i-write-to-standard-error-in-powershell. – Ohad Schneider Mar 22 '16 at 17:09
6

Why don't you think it is working? Keep in mind that PowerShell distinguishes between non-terminating errors like the one above and terminating errors like you get when you execute throw 'Access denied.'. Non terminating errors are written to stderr and logged in the $error collection but they don't stop processing of a script. This feature is extremely handy when you are processing (say deleting or copying) a bunch of files. You want to know which files couldn't be processed but you don't want the entire operation to stop on the first file that errors out.

PowerShell also gives you the option to "convert" non-terminating errors to terminating errors e.g.

Remove-Item c:\file-doesnt-exist -ErrorAction Stop; "Did I get here"

Notice in this case, execution stops and doesn't print out the string at the end. Try it without the -ErrorAction Stop and you will see the error but you will also see the string "Did I get here".

If you want to control the Catogory info you can use the -Category parameter like so:

PS> write-error "foo" -Category 'InvalidResult'
write-error "foo" -Category 'InvalidResult' : foo
    + CategoryInfo          : InvalidResult: (:) [Write-Error], WriteErrorExce..
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException

But the WriteErrorException is the mechanism (I think) by which this cmdlet raises the error. There is an Exception parameter but I've not had much luck using it.

Keith Hill
  • 194,368
  • 42
  • 353
  • 369
4

The problem here is that we've assumed a pattern for printing verbose, information, warning and error messages and expect the Write- cmdlets to form a set that follow this pattern.

But Write-Error is different and throws into doubt whether such a pattern was intended by the authors or was merely in the mind of the programmer. It's the Gaslighting of API design.

Write-Verbose

The Write-Verbose cmdlet writes text to the verbose message stream in PowerShell

Write-Warning

The Write-Warning cmdlet writes a warning message to the PowerShell host.

Write-Error

The Write-Error cmdlet declares a non-terminating error.

Oh. It does something different. It "declares" an error. It's like raising an event. It isn't writing text to standard error....

Luke Puplett
  • 42,091
  • 47
  • 181
  • 266
3

I believe you're seeing the expected output from that cmdlet. You're inputting the "Access denied." argument and it's outputting that to the host and most likely to the error stream as designed. You can confirm it is outputting to the $Error variable and it should be populated with the error you just inserted.

i.e.

PS C:\> $error.Clear()

PS C:\> Write-Error "access denied"

Write-Error "access denied" : access denied

    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException

PS C:\> $error

Write-Error "access denied" : access denied

    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException

I can see where that would be confusing though, perhaps MSFT should change the example error from something like "Access Denied" to "Foobar" for clarity.

Edit to address further question: The default errorAction for Write-Error is "continue", so to get it to behave like Write-Warning you would have to add -ErrorAction SilentlyContinue. Consider the following example:

PS E:\> $error.clear()
PS E:\> Write-Error 'test'
Write-Error 'test' : test
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException

PS E:\> Write-Error 'test2' -ErrorAction silentlycontinue  

PS E:\> $error[1]
Write-Error 'test' : test
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException

PS E:\> $error[0]
Write-Error 'test2' -ErrorAction silentlycontinue : test2
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
Toby Meyer
  • 316
  • 1
  • 6
  • 1
    Why do I get the "CategoryInfo not specified" WriteErrorException? The documentation says that it's optional... – sourcenouveau Mar 11 '11 at 13:57
  • It lists the category info as not specified is because what you're viewing is the standard error output, which is what Write-Error does; when any error is thrown in PS that is the template displayed... example: 'code` PS E:\> lkas The term 'lkas' is not recognized At line:1 char:7 + lkas <<<< + CategoryInfo : ObjectNotFound: (lkasjd:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException `code` The Category info is always listed; it shows up as not specified since you didn't specify it explicitly with the Write-Error command. – Toby Meyer Mar 11 '11 at 15:52
  • Sorry, I messed up the mini-markdown there. Note that I edited my original post to address the further scope of the question. Sorry for the mess :) – Toby Meyer Mar 11 '11 at 16:10