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

查看:22
本文介绍了.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 Continue 参数.或者,您可以将所有 .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天全站免登陆