Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

powershell - Is an exception from a .NET method a terminating or not-terminating error?

In this great article Keith explains the difference between terminating and non-terminating errors in Powershell. According to Keith exceptions thrown from calls to a member of a .NET object or type are non-terminating errors.

Indeed if we define this .NET class for testing:

$a = Add-Type 'public class bla { public static void bl() { throw new System.ApplicationException("test"); }}' -PassThru

And then this function:

function tst { 1 | write-host; $a::bl(); 2 | Write-host }

we will see that when tst function is called the exception appears to be non-terminating: the second Write-Host works.

But consider this:

function tst2 { try { tst } catch { "Catch!" } }

If we open the documentation, we can read that the catch responds to or handles terminating errors in scripts. Throughout the text of the articles the errors the article is dealing with qualified as "terminating" in numerous places.

So when we run the line above the second Write-Host does NOT run but the catch block does. It seems that our non-terminating error suddenly becomes terminating.

How come?

Another observation, is that with good old trap it's still non-terminating error:

function tst3 { tst trap { "Trap!" } }

Now, from practical perspective, what I want to achieve is the following. In a block of code I want to terminate on exceptions thrown from the .NET code. I want to leave terminating errors from cmdlets terminating and non-terminating errors from cmdlets non-terminating.

How do I achieve this?

Example:

Do-Something
Call::Something()
Do-SomethingElse
Call::SomethingElse()
Do-YetMoreSomething
Call::YetMoreSomething()

I want to terminate on all the exceptions from .NET calls above. I also want to terminate on terminating errors from the cmdlets. I do not want to terminate on non-terminating errors from the cmdlets.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Yeah, this came up on the PowerShell MVP email list earlier this year. PowerShell changes its error handling behavior for .NET exceptions depending on whether or not there is an outer try/catch. This is just speculation but I'm guessing that this was for simple scripting scenarios. That is, if the scripter (admin) messes up calling a .NET method and that generates an exception, the PowerShell team didn't want that to cease execution of the entire script. Once V2 came along and introduced proper try/catch I'm guessing they had to revisit that decision and came up with the current compromise.

That said, working around this is a pain as you've discovered. You could set $ErrorActionPreference to Stop at the script level and then for every cmdlet that can generate non-terminating errors use the -ErrorAction Continue parameter. Or you could put all of your .NET invocations within an advanced function(s) and then call that function(s) with the parameter -ErrorAction Stop. I wish there was a better answer but after reviewing that MVP thread, I didn't see any better solutions.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...