.NET方法的异常是终止错误还是未终止错误? [英] Is an exception from a .NET method a terminating or not-terminating error?

查看:97
本文介绍了.NET方法的异常是终止错误还是未终止错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此出色的文章中 Keith解释了Powershell中终止错误和非终止错误之间的区别。根据Keith的说法,从调用.NET对象或类型的成员引发的异常是非终止错误。

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.

实际上,如果我们定义此.NET类进行测试:

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

然后使用此函数:

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

我们将看到,调用tst函数时,异常似乎是非终止的:第二个 Write-Host 有效。

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

但是请考虑以下问题:

function tst2 { try { tst } catch { "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.

因此,当我们在第二个Write-Host上方运行该行时,不运行,但是catch块可以运行。似乎我们的非终止错误突然变得终止了。

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.

怎么来?

另一个观察结果是,具有良好的旧陷阱,它仍然是非终止错误:

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

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

现在,从实际的角度来看,我要实现的目标如下。在代码块中,我想终止从.NET代码引发的异常。我想让cmdlet终止的终止错误和cmdlet的非终止错误保持不终止。

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.

如何实现?

示例:

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

我想终止所有来自.NET调用的异常以上。我也想终止来自cmdlet的错误。我不想终止来自cmdlet的非终止错误。

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.

推荐答案

是的,这是在PowerShell MVP电子邮件中出现的今年早些时候列出。 PowerShell会根据是否存在外部try / catch来更改.NET异常的错误处理行为。这只是猜测,但我猜测这是针对简单脚本场景的。也就是说,如果脚本编写者(管理员)搞砸了.NET方法的调用并产生了异常,那么PowerShell团队就不希望这样做停止整个脚本的执行。当V2出现并引入适当的try / catch时,我想他们必须重新考虑该决定并提出当前的折衷方案。

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.

这就是您发现的解决方法。您可以在脚本级别将$ ErrorActionPreference设置为 Stop ,然后对于每个可能产生非终止错误的cmdlet,使用 -ErrorAction继续参数。或者,您可以将所有.NET调用放在高级函数中,然后使用参数 -ErrorAction Stop 调用该函数。我希望有一个更好的答案,但是在查看了该MVP线程之后,我没有看到任何更好的解决方案。

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.

这篇关于.NET方法的异常是终止错误还是未终止错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆