如何在特定异常上终止.NET应用程序 - 可能没有堆栈展开?

时间:2016-02-19 10:59:43

标签: c# .net exception-handling c++-cli corrupted-state-exception

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

"崩溃" (即{+ 1}}和其他Corrupted State Exceptions)在C ++代码中将正确处理("非 - "),它们将直接导向我的System.AccessViolationException处理程序(日志)然后应用程序将终止,如果这样配置(它是),写一个WER转储文件。

对于此应用程序,我已确定AppDomain.CurrentDomain.UnhandledException始终是一个错误,尤其是,因为某些C ++ / CLI访问冲突错误将报告此错误而不是AV。

有没有办法让.NET 在异常边界上捕获System.NullReferenceException(在这种情况下我的NullReferenceException回调),而是直接终止应用,< em>没有展开堆栈,基本上&#34;跳跃&#34;直接到OnTimer

2 个答案:

答案 0 :(得分: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中可能包含的日志记录代码(或者有一个由两者调用的常用方法)

答案 1 :(得分:1)

事实FirstChanceException实际上是一个简单的&#34;全球异常过滤器让我走上了轨道(它是否是&#34;右边&#34;轨道还有待观察):

我们在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

显然,要使它工作,你需要更多的配置操作,但这似乎正是我想要的。 : - )