如何在.NET 8中捕获访问冲突异常并优雅地退出应用程序?

编程语言 2026-07-12

部分代码抛出 AccessViolationException;代码不在我的控制之下;我无法修复这个问题。当抛出这个异常时,我的应用程序会崩溃。我正在使用控制台应用程序和WinForms应用程序,两者使用相同的代码。两种变体中的问题都是一样的。

我清楚自己不能也不应该处理这个异常;这就是它会导致应用程序崩溃的原因。我可以在事件查看器中查看日志。我也不想处理这个异常;我只是想捕获它,以便写入日志,然后让应用程序以任意方式结束。因此应用程序崩溃不是我的问题。我需要在它崩溃之前写入日志,这样就不必去事件查看器查看到底哪里出错了。

我发现下面这些问题很有帮助:

Stack Overflow上还有其他几个相关问题在谈论这个问题;但它们都关于旧版.NET Framework。

在较旧版本的.NET Framework中,有一个设置需要在 app.config 中进行:

<runtime>
    <legacyCorruptedStateExceptionsPolicy enabled="true" />
</runtime>

我尝试了这个,在.NET Framework 4中对我有用。

还有一个属性 [HandleProcessCorruptedStateExceptions],在.NET 8中已被弃用。我仍然尝试了它,但不起作用;应用程序仍然崩溃;下面是代码:

[HandleProcessCorruptedStateExceptions]
private bool MethodThatThrowsException(string filePath)
{
    ...
    ...
}

根据这些问题的回答,还可以使用另一个属性 [SecurityCritical];但它需要完全信任(Full Trust),这并非每次都可能实现。

在其中一个问题中解释的 COMPlus_legacyCorruptedState­­ExceptionsPolicy 环境变量方法也不起作用。在我的应用程序启动阶段添加以下代码仍然会使应用程序崩溃:

static class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        Environment.SetEnvironmentVariable("COMPlus_legacyCorruptedState­­ExceptionsPolicy", "1");

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

看起来这些解决方案在.NET 8中已不再受支持: https://github.com/dotnet/runtime/issues/12077#issuecomment-554933927
https://github.com/dotnet/runtime/issues/12077#issuecomment-555048590

所以唯一剩下的选项是 legacyCorruptedStateExceptionsPolicy。我想在面向.NET 8的应用程序中使用它。我应该在.NET 8中如何以及在哪里设置这个选项?在.NET 8中没有 app.config 文件。.runtimeconfig.json 是不是可行的方法?即便如此,如何在其中进行配置?

解决方案

下面是一个使用环境变量 COMPlus_legacyCorruptedStateExceptionsPolicy 的简单示例。

public static int Main(string[] args)
{
    if (args.Length == 0)
    {
        Environment.SetEnvironmentVariable("COMPlus_legacyCorruptedStateExceptionsPolicy", "1");
        Process.Start(Process.GetCurrentProcess().MainModule.FileName, "1");
    }
    else
    {
        try
        {
            ThrowException();
        }
        catch (AccessViolationException ex)
        {
            Console.WriteLine("Caught: " + ex);
        }
    }

    return 0;
}

public static unsafe void ThrowException()
{
    int* ptr = (int*)0x12345678;
    *ptr = 1;
}

运行它时,会显示:

Caught: System.AccessViolationException: Attempted to read or write protected memory.
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章