In PowerShell, we draw the distinction between terminating and non-terminating errors. The way to think about the distinction is a what should happen if I pipeline a set of objects to an operation. There are certain errors which mean that there is little to no change that any subsequent object could be processed correctly (for instance if you had a connection that got lost). These are terminating errors.
Then there are errors that have no effect on the next operation (for instance, just because you couldn’t kill one process doesn’t mean you won’t be able to kill the next one). These are non-terminating errors.
Users get to control what happens when a cmdlet issues a non-terminating error. This is done via the common parameter -ErrorAction. To examine what values this parameter can take, let’s use my favorite discovery technique – input garbage and see what happens:
PS>stop-process 13 -ErrorAction asdf
Stop-Process : Cannot bind parameter ‘ErrorAction’. Cannot convert value “asdf” to type “System.Management.Automation.ActionPreference” due to invalid enumeration values. Specify one of the following enumeration values and try again. The possible enumeration values are “SilentlyContinue, Stop, Continue, Inquire“.
At line:1 char:29
+ stop-process 13 -ErrorAction <<<< asdf
Great. So now we know that values we can give it.
It just so happens that the thing I do most often is to use the value SilentlyContinue.
This isn’t so bad in a script but it is quite painful to be a power user and have to type out -ErrorAction SilentlyContinue. Well because this is PowerShell, you only need to provide enough of the parameter to disambiguate AND we provided an alias “EA” so all you have to type is -EA SilentlyContinue.
So that is better but it is still pretty painful. So it begs the question – why “SilentlyContinue” vs “Ignore”. Sadly, there is no good answer to this one. I’ve love to say that someone else on the team made this horrible call but there is a good chance that I screwed that one up (it was a long time ago). The sad part is that we realized we made a mistake a long time ago but because of the way we develop code and get hardcore about what changes are made when – it never got to bubble up the queue to get fixed. 10,000 apologizes for that one.
So – were do we go from here?
One of the features we have on our dream-list is that when you are specifying an ENUM, PowerShell should be smart enough to let you type just enough to disambiguate and we’ll figure out the rest. This would allow you to type: -ea si . Now again, this is not want you want to see in a production script but it would be pretty great for quick interactive use.
That feature remains a dream and not a plan (at this point).
Well imagine how delighted I was to see a code example from Keith Hill that solves my problem. I forgot that ENUMs are really just INTs. .NET knows how to cast a string into an ENUM int and we are leveraging that. BUT is also will cast an INT into an ENUM int.
PS>stop-process 13 -EA 0
PS>stop-process 13 -EA 4
Stop-Process : Cannot bind parameter ‘ErrorAction’. Cannot convert value “4” to type “System.Management.Automation.ActionPreference” due to invalid enumeration values. Specify one of the following enumeration values and try again. The possible enumeration values are “SilentlyContinue, Stop, Continue, Inquire”.
At line:1 char:20
+ stop-process 13 -EA <<<< 4
In other words: “-EA 0″ is exactly the same as “-ErrorAction SilentlyContinue” except that it is 1/6th the length!
So when you see a list of ENUMs, it is TYPICALLY (but not always) the case that the values start at 0 and increment. In all cases, if you know the int value of the enum, you can just use that.
10,000 thanks to Keith Hill for pointing this out. Boy you just gotta love the PowerShell community!
Jeffrey Snover [MSFT]
Windows Management Partner 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