1

我有一个由 C# 和 C++ 代码组成的 .NET 应用程序(服务)。

C++ 代码中的“崩溃”(即System.AccessViolationException和其他损坏状态异常)将被(“非”)正确处理,它们将直接导致我的AppDomain.CurrentDomain.UnhandledException处理程序(记录),然后应用程序将终止,写入 WER 转储文件,如果如此配置(就是这样)。

对于这个应用程序,我确定这System.NullReferenceException始终是一个错误,特别是因为一些 C++/CLI 访问冲突错误会报告这个错误而不是 AV。

有没有办法让.NET捕获NullReferenceException异常边界(OnTimer在这种情况下是我的回调),而是直接终止应用程序,而不展开堆栈,基本上直接“跳转”到AppDomain.CurrentDomain.UnhandledException

4

2 回答 2

2

你可以:

AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;

接着

static void CurrentDomain_FirstChanceException(object sender, FirstChanceExceptionEventArgs e)
{
    if (e.Exception is NullReferenceException)
    {
        Environment.FailFast("FailFast", e.Exception);
    }
}

Environment.FailFast: _

在将消息写入 Windows 应用程序事件日志后立即终止进程,然后将该消息包含在向 Microsoft 报告的错误中。

此方法在不运行任何活动的 try/finally 块或终结器的情况下终止进程。

显然,CurrentDomain_FirstChanceException您可以复制您可能拥有的日志记录代码UnhandledException(或者有一个由两者调用的通用方法)

于 2016-02-19T11:14:28.773 回答
1

实际上FirstChanceException是一个“简单”的全局异常过滤器的事实让我走上了正轨(它是否是“正确的”轨道还有待观察):

我们已经在 CLI 中有异常过滤器

如果一个人有幸在 C# 6 中工作,那么它很简单:

        try
        {
            throw new NullReferenceException("No, Really");
        }
        catch(Exception ex) when (FilterExType(ex))
        {
            Console.WriteLine($"2: Caught 'any' exception: {ex}");
        }

    static bool FilterExType(Exception ex)
    {
        if (ex is NullReferenceException)
        {
            Environment.FailFast("BOOM from C#!", ex);
        }
        // always handle if we return
        return true;
    }

对于我们这些(像我一样)坚持早期版本的人,我们可以通过委托/lambda通过VB.NET路由过滤:

        try {
            VbFilterLib.FilteredRunner.RunFiltered(() =>
            {
                throw new NullReferenceException("Via VB.NET");
            });
        } 
        catch (Exception ex)
        {
            Console.WriteLine("1: Caught 'any' exception: {0}", ex");
        }

使用 VB(请耐心等待,VB.NET远非我精通的语言):

Public Class FilteredRunner
    Delegate Sub VoidCode()

    Private Shared Function FilterAction(x As Exception) As Boolean
        If TypeOf x Is NullReferenceException Then
            Environment.FailFast("Abort program! Investigate Bug via crash dump!", x)
        End If
        ' Never handle here:'
        Return False
    End Function

    Public Shared Sub RunFiltered(code As VoidCode)
        Try
            code.Invoke()
        Catch ex As Exception When FilterAction(ex)
            Throw New InvalidProgramException("Unreachable!", ex)
        End Try
    End Sub

End Class

显然,要使其工作,您需要更多的配置索具,但这似乎正是我想要的。:-)

于 2016-02-19T20:16:24.670 回答