-ErrorAction and -ErrorVariable

-ErrorAction and -ErrorVariable

Rate This
  • Comments 14

Let me take a minute to tell you about 2 of my favorite things in Windows PowerShell:  -ErrorAction and –ErrorVariable

You may have heard me talk about being maniacal about doing a great job with error handling ... this is one the cornerstones of our architecture.

Here is the background:  Cmdlets are implemented by subclassing a base class.  The engine reflects against this class looking for public properties that have a .net attribute on them identifying them as a PARAMETER.  Why is this a good idea?  Well think about it, the base class can also have public properties with the PARAMETER attribute.  And that's exactly what we do.  We call these Common Parameters (because I failed to convince our writers that it was a noble and worthwhile task to teach the planet the meaning of the word "ubiquitous"). 

You might be asking yourself - how would I find out more about common parameters?
Hmmm... so you want to "get help about common parameters".  Hmmm, I wonder want a good way to express this idea in PowerShell would be ......
How about: 

PS> get-help about_CommonParameters
TOPIC
    Common Parameters

SHORT DESCRIPTION
    Parameters that every cmdlet supports.

LONG DESCRIPTION
    Windows PowerShell includes several common parameters that all
    cmdlets support. This feature provides a consistent interface to
    Windows PowerShell.

    When a cmdlet supports a common parameter, the use of the parameter
    does not cause an error. However, the parameter might not have any
    effect in some cmdlets.

    The common parameters are:

    Parameter      Description
    ---------      --------------------------------------------------
    Verbose        Boolean. Generates detailed information about the
                   operation, much like tracing or a transaction log.
                   This parameter is effective only in cmdlets that
                   generate verbose data.

    Debug          Boolean. Generates programmer-level detail about the
                   operation. This parameter is effective only in cmdlets
                   that generate debug data.

    ErrorAction    Enum. Determines how the cmdlet responds when an error
                   occurs. Values are: Continue [default], Stop,
                   SilentlyContinue, Inquire.

    ErrorVariable  String. Specifies a variable that stores errors from
                   the command during processing. This variable is
                   populated in addition to $error.

    OutVariable    String. Specifies a variable that stores output from
                   the command during processing.

    OutBuffer      Int32. Determines the number of objects to buffer
                   before calling the next cmdlet in the pipeline.
 

    In addition to the common parameters, there are two parameters that
    cmdlets support if they change the system state.

    Parameter     Description
    ---------     -------------------------------------------------------

    WhatIf        Boolean. Explains what will happen if the command is
                  executed, without actually executing the command.

    Confirm       Boolean. Prompts the user for permission before
                  performing any action that modifies the system.

SEE ALSO
    For information about parameters, type:

        help about_Parameter

You think it, you type it, you get it.  :-)

 So back to -ErrorAction and -ErrorVariable.  These are implemented by the engine on behalf of the Cmdlet - the developer doesn't have to do anything.  They just call WriteError() and we do the rest. 

Here is the easiest way to show this working:

PS> Stop-Process 13,23
Stop-Process : Cannot find a process with the process identifier 13.
At line:1 char:13
+ Stop-Process  <<<< 13,23
Stop-Process : Cannot find a process with the process identifier 23.
At line:1 char:13
+ Stop-Process  <<<< 13,23

PS> Stop-Process 13,23 -ErrorAction Stop  # Only 1 error
Stop-Process : Command execution stopped because the shell variable "ErrorA
ctionPreference" is set to Stop: Cannot find a process with the process ide
ntifier 13.
At line:1 char:13
+ Stop-Process  <<<< 13,23 -ErrorAction Stop  # Only 1 error

PS> Stop-Process 13,23 -ErrorAction silentlycontinue  # No errors

PS> Stop-Process 13,23 -ErrorAction inquire  # ASK
Confirm
Cannot find a process with the process identifier 13.
[Y] Yes  [A] Yes to All  [H] Halt Command  [S] Suspend  [?] Help
(default is "Y"):h
Stop-Process : Command execution stopped because the user selected the Halt
 option.
At line:1 char:13
+ Stop-Process  <<<< 13,23 -ErrorAction inquire  # ASK
PS>
PS>
PS> Stop-Process 13,23 -ErrorVariable a -ErrorAction SilentlyContinue

PS> $a[0]
Stop-Process : Cannot find a process with the process identifier 13.
At line:1 char:13
+ Stop-Process  <<<< 13,23 -ErrorVariable a -ErrorAction SilentlyContinue

PS> $a[0] |fl * -Force

Exception             : Microsoft.PowerShell.Commands.ProcessCommandExcepti
                        on: Cannot find a process with the process identifi
                        er 13.
TargetObject          : 13
CategoryInfo          : ObjectNotFound: (13:Int32) [Stop-Process], ProcessC
                        ommandException
FullyQualifiedErrorId : NoProcessFoundForGivenId,Microsoft.PowerShell.Comma
                        nds.StopProcessCommand
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo

PS> $a |ft TargetObject -force -auto
TargetObject
------------
          13
          23

 

Now one thing that is not obvious to people is that you can specify a “+” in front of the variable name for ErrorVariable and we will ADD the errors to that variable.

PS> $err=@()
PS> stop-process 13 -ea silentlycontinue -ErrorVariable err
PS> $err.count
1

PS> stop-process 23 -ea silentlycontinue -ErrorVariable +err
PS> $err.count
2
PS> $err
Stop-Process : Cannot find a process with the process identifier 13.
At line:1 char:13
+ stop-process  <<<< 13 -ea silentlycontinue -ErrorVariable err
Stop-Process : Cannot find a process with the process identifier 23.
At line:1 char:13
+ stop-process  <<<< 23 -ea silentlycontinue -ErrorVariable +err

Lastly,  you don’t need to type out –ErrorAction or –ErrorVariable, we have defined parameter aliases for these so you can just type –EA and -EV

Enjoy

Jeffrey Snover [MSFT]
Windows PowerShell/MMC Architect
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

Leave a Comment
  • Please add 5 and 2 and type the answer here:
  • Post
  • I liked very much the "ErrorVariable", it's "something" like the named matches (?<name>match) thing in -match because it let you keep information stored to use it as needed.

    Great stuff Jeffrey, thanks

    Jorge Mestre

    A Linux user :)

    A Windows at work ;)

  • I have a question about ErrorAction.  When I do the following:

    PS C:\pscripts> $A = get-wmiobject -namespace root\directory\ldap ds_Computer | Select-Object DS_Name

    PS C:\pscripts> $B = $A | foreach  { get-wmiobject Win32_ComputerSystem -computerName $_ -erroraction silentlycontinue}

    If the second get-wmiobject call fails to find any of the machines listed in the first, then $B is null.  Otherwise if all of the machines are found then $B contains information about each machine.  Why is the erroraction not causing the error to be ignored?

  • Darrel -- can you reproduce this in a simpler manner?  For example, if your machine is "Darrel1", try this:

    "Darrel1","missing_computer" | foreach { Get-WmiObject ... }

    In that situation, I still get the information back.

    Lee

  • I had tried using a simple array prior to finding the "silentlycontinue" option.  

    However, my mistake was not using $_.DS_Name in the foreach{}

    Thanks for the kick in the right direction!

  • This post is da bomb!  Just what I was looking for.

  • For some reason, -ErrorVariable seems completely broken in 2010 Exchange Management Shell. Anyone else seen this??? :)

  • @camy - please file a bug.  This happens for all remote sessions.

    jps

  • @camy - there is a workaround.  Specify a global variable.

    verb-noun -ErrorVariable "global:myVar"

    That should work till we get this fixed.

    Thanks for bringing it to our attention and I'm sorry you experienced this.

    jps

  • hm, I don't understand how this works together with try/catch

    try

    {

    Get-Content 'non-existing-file.txt' -ErrorAction STOP

    }

    catch [System.Management.Automation.ItemNotFoundException]

    {

    Write-Output 'Got it'

    }

    it doesn't get caught.

    Same with System.Management.Automation.SessionStateException

    (but it does with more generic catches such as System.Object)

    I wish there were no "error" concept, just exceptions, like in other .NET languages.

  • To fix your problems use the code below:

    This code will catch all errors due to the -erroraction stop

    Next you will trow the Original non terminating error back in  a new try/catch but because you trow it it becaomes a terminating error and you can catch it.

    try

    {

    Get-MailboxStatistics dummy@domain.nl -ErrorAction stop

    }

    catch

    {

    "fullname:"

    $_.gettype().FullName

    "Exception:"

    $_.exception.Gettype().Fullname

    "message:"

    $_.exception.Message

    try {throw $_.exception}

    catch [System.Management.Automation.RemoteException]

    {

    Write-host -ForegroundColor Green "cached Non terminating error remote exception"

    }

    }

  • What's the difference between "-ErrorAction SilentlyContinue" and "-ErrorAction Ignore"?

  • what about alias -ea "quick" parametrs 0,1,2,3,4,5 ?

    where can i read about it?

  • Is the "-ErrorAction Ignore" and  "-ErrorAction SilentlyContinue" are bypassed when the error is about "Elevation"

    The following command will give me an error even tought I have used the error action parameter.Get

    PS C:\ (1) > Get-WindowsEdition -Online -ErrorAction SilentlyContinue

    Get-WindowsEdition : The requested operation requires elevation.

    At line:1 char:1

    + Get-WindowsEdition -Online -ErrorAction SilentlyContinue

    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

       + CategoryInfo          : NotSpecified: (:) [Get-WindowsEdition], COMException

       + FullyQualifiedErrorId : Microsoft.Dism.Commands.GetWindowsEditionCommand

    OR

    PS C:\ (2) > Get-WindowsEdition -Online -ErrorAction Ignore

    Get-WindowsEdition : The requested operation requires elevation.

    At line:1 char:1

    + Get-WindowsEdition -Online -ErrorAction Ignore

    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

       + CategoryInfo          : NotSpecified: (:) [Get-WindowsEdition], COMException

       + FullyQualifiedErrorId : Microsoft.Dism.Commands.GetWindowsEditionCommand

  • Hi Martin,

    -ErrorAction is only used to ignore non-terminating errors. If PowerShell doesn't know how to handle an exception, it can't simply ignore it. Instead, you have to use try/catch.

    Check out this StackExchange post for more info: stackoverflow.com/.../why-does-an-error-still-show-when-i-specify-erroraction-silentlycontinue

    -Joey

    PM, PowerShell

Page 1 of 1 (14 items)