代码之家  ›  专栏  ›  技术社区  ›  Stefan Steiger Marco van de Voort

控制台应用程序中的.NET全局异常处理程序

  •  176
  • Stefan Steiger Marco van de Voort  · 技术社区  · 15 年前

    AppDomain currentDomain = AppDomain.CurrentDomain;
    currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyExceptionHandler);
    

    但如何为控制台应用程序定义全局异常处理程序?
    currentDomain似乎无法工作(.NET 2.0)?

    编辑:

    啊,愚蠢的错误。
    在VB.NET中,需要在currentDomain前面添加“AddHandler”关键字,否则在IntelliSense中看不到UnhandledException事件。。。

    4 回复  |  直到 9 年前
        1
  •  288
  •   Hans Passant    7 年前

    不,那是正确的方法。这正是它应该发挥的作用,你可以从以下方面着手:

    using System;
    
    class Program {
        static void Main(string[] args) {
            System.AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
            throw new Exception("Kaboom");
        }
    
        static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e) {
            Console.WriteLine(e.ExceptionObject.ToString());
            Console.WriteLine("Press Enter to continue");
            Console.ReadLine();
            Environment.Exit(1);
        }
    }
    

    请记住,您无法捕获由抖动以这种方式生成的类型和文件加载异常。它们发生在Main()方法开始运行之前。捕捉这些需要延迟抖动,将有风险的代码移到另一个方法中,并对其应用[MethodImpl(MethodImplOptions.noinline)]属性。

        2
  •  23
  •   BlueMonkMN    15 年前

    如果您有一个单线程应用程序,那么可以在Main函数中使用一个简单的try/catch,但是,这不包括可能在Main函数之外抛出的异常,例如在其他线程上抛出的异常(如其他注释中所述)。此代码演示了即使您尝试在Main中处理异常,异常如何导致应用程序终止(请注意,如果您在异常发生之前按enter键并允许应用程序正常退出,程序将如何正常退出,但如果您让它运行,它将非常不愉快地终止):

    static bool exiting = false;
    
    static void Main(string[] args)
    {
       try
       {
          System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
          demo.Start();
          Console.ReadLine();
          exiting = true;
       }
       catch (Exception ex)
       {
          Console.WriteLine("Caught an exception");
       }
    }
    
    static void DemoThread()
    {
       for(int i = 5; i >= 0; i--)
       {
          Console.Write("24/{0} =", i);
          Console.Out.Flush();
          Console.WriteLine("{0}", 24 / i);
          System.Threading.Thread.Sleep(1000);
          if (exiting) return;
       }
    }
    

    static bool exiting = false;
    
    static void Main(string[] args)
    {
       try
       {
          System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
          AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
          demo.Start();
          Console.ReadLine();
          exiting = true;
       }
       catch (Exception ex)
       {
          Console.WriteLine("Caught an exception");
       }
    }
    
    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
       Console.WriteLine("Notified of a thread exception... application is terminating.");
    }
    
    static void DemoThread()
    {
       for(int i = 5; i >= 0; i--)
       {
          Console.Write("24/{0} =", i);
          Console.Out.Flush();
          Console.WriteLine("{0}", 24 / i);
          System.Threading.Thread.Sleep(1000);
          if (exiting) return;
       }
    }
    

    所以在我看来,最干净的处理方法 在控制台应用程序中

    static bool exiting = false;
    
    static void Main(string[] args)
    {
       try
       {
          System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
          demo.Start();
          Console.ReadLine();
          exiting = true;
       }
       catch (Exception ex)
       {
          Console.WriteLine("Caught an exception");
       }
    }
    
    static void DemoThread()
    {
       try
       {
          for (int i = 5; i >= 0; i--)
          {
             Console.Write("24/{0} =", i);
             Console.Out.Flush();
             Console.WriteLine("{0}", 24 / i);
             System.Threading.Thread.Sleep(1000);
             if (exiting) return;
          }
       }
       catch (Exception ex)
       {
          Console.WriteLine("Caught an exception on the other thread");
       }
    }
    
        3
  •  12
  •   BlackICE    15 年前

    您还需要处理来自线程的异常:

    static void Main(string[] args) {
    Application.ThreadException += MYThreadHandler;
    }
    
    private void MYThreadHandler(object sender, Threading.ThreadExceptionEventArgs e)
    {
        Console.WriteLine(e.Exception.StackTrace);
    }
    

    喔,对不起,这是针对winforms的,对于您在控制台应用程序中使用的任何线程,您必须将其包含在try/catch块中。遇到未处理异常的后台线程不会导致应用程序结束。

        4
  •  1
  •   Russell Jonakin    5 年前

    我刚刚继承了一个旧的VB.NET控制台应用程序,需要设置一个全局异常处理程序。由于这个问题多次提到VB.NET,并用VB.NET标记,但这里的所有其他答案都是C#,因此我想我也应该为VB.NET应用程序添加确切的语法。

    Public Sub Main()
        REM Set up Global Unhandled Exception Handler.
        AddHandler System.AppDomain.CurrentDomain.UnhandledException, AddressOf MyUnhandledExceptionEvent
    
        REM Do other stuff
    End Sub
    
    Public Sub MyUnhandledExceptionEvent(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs)
        REM Log Exception here and do whatever else is needed
    End Sub
    

    我用了 REM 注释标记而不是单引号,因为堆栈溢出似乎可以更好地处理语法高亮显示 雷姆 .

        5
  •  -13
  •   Rodney S. Foley    15 年前

    您正在尝试的应该根据.NET2.0的MSDN文档工作。你也可以在主控台应用程序的入口点附近尝试try/catch。

    static void Main(string[] args)
    {
        try
        {
            // Start Working
        }
        catch (Exception ex)
        {
            // Output/Log Exception
        }
        finally
        {
            // Clean Up If Needed
        }
    }
    

    在主线程中 ). 它可以是优雅的,甚至可以重新启动它,如果你想,或者你可以让应用程序死,并记录异常。如果你想做任何清理,你会加一个finally。 每个线程都需要自己的高级异常处理,类似于主线程。