(未处理AccessViolationException)如何在C#中实现HandleProcessCorruptedStateException?

时间:2019-05-13 03:04:18

标签: c# visual-studio error-handling

我遇到了一个问题,即在我运行程序约一天后,AccessViolationException未得到处理。

(更多信息:我正在使用Visual Studio 2010)

但是,它没有说明发生此异常的位置,给了我两个选择,分别是“确定”和“继续”。当我按OK时,什么也没发生,所以我按了继续,程序停止了调试。

当我尝试找到解决方案时,我了解到可以实施HandleProcessCorruptedStateExceptions来解决此问题。但是,我不知道从哪里开始。

我是否仅仅包含以下代码?在哪里包含这些代码?

[HandleProcessCorruptedStateExceptions] 
[SecurityCritical]
public static int Main() 
{ 
   try
     {
       // Catch any exceptions leaking out of the program CallMainProgramLoop(); 
     }
   catch (Exception e) 
       // We could be catching anything here 
     {
         // The exception we caught could have been a program error
        // or something much more serious. Regardless, we know that
        // something is not right. We'll just output the exception 
       // and exit with an error. We won't try to do any work when
       // the program or process is in an unknown state!

        System.Console.WriteLine(e.Message); 
        return 1; 
     } 

  return 0; 

}

或者,我也可以执行此legacyCorruptedStateExceptionsPolicy,但是它说我应该在配置文件中输入所需的语句。在哪里可以找到配置文件?

感谢所有回复!

1 个答案:

答案 0 :(得分:0)

问题的实际答案是here,我真的不应该再回答,但是我想向您展示一些代码示例,并且我不想在注释中写它:)

在我的一个项目中,有时会有一个不可预测的异常。为了捕捉它,我在Program.cs中编写了这段代码:

[STAThread]
static void Main()
{
    // add UnhandledException handler
    AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new MainForm());
}

private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e)
{
    // prepare message for user
    var message = "There was an unknown exception while running <app_name>!";
    var exception = e.ExceptionObject as Exception;

    if (exception != null)
    {
        // change message if there was actual exception
        message = $"There was an {exception.GetType().Name} exception while running <app_name>! {exception.Message}";
        // adding inner exceptions messages
        var innerException = exception.InnerException;
        while (innerException != null)
        {
            message += $"\r\n-> {innerException.GetType().Name}: {innerException.Message}";
            innerException = innerException.InnerException;
        }
#if DEBUG
        // add tracing info
        message += $"\r\n\r\n{GetStackTrace(exception)}";
#endif
    }
    if (e.IsTerminating) message += "\r\n\r\n<app_name> will be closed.";

    // showing message to the user
    MessageBox.Show(message, "Unhandled Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
#if DEBUG
private static string GetStackTrace(Exception exception)
{
    var trace = new System.Diagnostics.StackTrace(exception, fNeedFileInfo: true);
    var frames = trace.GetFrames()
        .Select((f, i) => {
            var filename = f.GetFileName();
            var methodInfo = f.GetMethod();

            var frame = $"#{i} in the method {methodInfo.DeclaringType.FullName}.{methodInfo.Name}()";
            if (filename != null) frame += $" (source file: {System.IO.Path.GetFileName(filename)}@{f.GetFileLineNumber()}:{f.GetFileColumnNumber()})";

            return frame;
        });

    return $"Full stack trace ({trace.FrameCount} frames total):\r\n{string.Join("\r\n", frames)}";
}
#endif

现在,当发生未处理的异常时-将出现一个消息框,其中显示完整的异常消息(和内部异常消息)。对于调试构建,还有完整的堆栈跟踪,其中包含发生异常的方法名称,行号和源文件名。

关于HandleProcessCorruptedStateExceptions

您在评论中提到了HandleProcessCorruptedStateExceptions属性。 The docs明确指出,除非绝对确定需要使用,否则不要使用它。

  

损坏的流程状态异常是表明以下情况的异常:   进程状态已损坏。我们不推荐   在这种状态下执行您的应用程序。

     

默认情况下,公共语言运行库(CLR)不会提供这些   托管代码和try/catch块(以及其他   不会为它们调用异常处理子句)。 如果您是   绝对确定,您要保持对这些内容的处理   例外情况,您必须应用   方法的HandleProcessCorruptedStateExceptionsAttribute属性   要执行其异常处理子句。 CLR提供   适用的异常条款的损坏的流程状态异常   仅在同时具有   HandleProcessCorruptedStateExceptionsAttribute和   SecurityCriticalAttribute attributes

损坏的进程状态意味着会发生一些真正的灾难性事件,并且您的应用现在可以更安全地死亡。如果仍然不够害怕,可以使用上面示例中的Main()方法,并设置HandleProcessCorruptedStateExceptions属性:

[STAThread]
[HandleProcessCorruptedStateExceptions, SecurityCritical]
static void Main()
{
    try
    {
        // add UnhandledException handler
        // AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
        // * in this particular case is not quite useful to handle this exceptions,
        //   because you already wrap your entire application in a try/catch block

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MainForm());
    }
    catch (Exception ex)
    {
        // handle it somehow
    }
}