问:我想为控制台应用程序中未处理的异常定义一个全局异常处理程序。在asp.net中,可以在global中定义。在Windows应用程序/服务中,可以如下定义

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

但是如何为控制台应用程序定义全局异常处理程序呢? currentDomain似乎不工作(。Net 2.0) ?

编辑:

啊,愚蠢的错误。 在VB。NET,一个人需要在currentDomain前添加“AddHandler”关键字,否则在智能感知中看不到UnhandledException事件… 这是因为VB。NET和c#编译器处理事件的方式是不同的。


当前回答

你所尝试的应该根据。net 2.0的MSDN文档来工作。你也可以在主机应用程序的入口点附近尝试try/catch。

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

现在,catch将处理主线程中未捕获的任何内容。它可以很优雅,甚至可以重新启动,如果你想的话,或者你可以让应用程序死亡并记录异常。如果你想要做任何清理,你会在最后加一个。每个线程都需要自己的高级异常处理,类似于主线程。

经过编辑,澄清了BlueMonkMN所指出的关于线程的观点,并在他的回答中详细说明了这一点。

其他回答

不,这才是正确的做法。这完全是它应该工作的,你可以从一些东西:

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.NoInlining)]属性。

你所尝试的应该根据。net 2.0的MSDN文档来工作。你也可以在主机应用程序的入口点附近尝试try/catch。

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

现在,catch将处理主线程中未捕获的任何内容。它可以很优雅,甚至可以重新启动,如果你想的话,或者你可以让应用程序死亡并记录异常。如果你想要做任何清理,你会在最后加一个。每个线程都需要自己的高级异常处理,类似于主线程。

经过编辑,澄清了BlueMonkMN所指出的关于线程的观点,并在他的回答中详细说明了这一点。

你还需要处理线程中的异常:

static void Main(string[] args) {
Application.ThreadException += MYThreadHandler;
}

private void MYThreadHandler(object sender, Threading.ThreadExceptionEventArgs e)
{
    Console.WriteLine(e.Exception.StackTrace);
}

哦,对不起,这是winforms,对于你在控制台应用程序中使用的任何线程,你都必须在一个try/catch块中封装。遇到未处理异常的后台线程不会导致应用程序结束。

我刚继承了一个老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注释标记而不是单引号,因为Stack Overflow似乎用REM更好地处理语法高亮显示。

If you have a single-threaded application, you can use a simple try/catch in the Main function, however, this does not cover exceptions that may be thrown outside of the Main function, on other threads, for example (as noted in other comments). This code demonstrates how an exception can cause the application to terminate even though you tried to handle it in Main (notice how the program exits gracefully if you press enter and allow the application to exit gracefully before the exception occurs, but if you let it run, it terminates quite unhappily):

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;
   }
}

You can receive notification of when another thread throws an exception to perform some clean up before the application exits, but as far as I can tell, you cannot, from a console application, force the application to continue running if you do not handle the exception on the thread from which it is thrown without using some obscure compatibility options to make the application behave like it would have with .NET 1.x. This code demonstrates how the main thread can be notified of exceptions coming from other threads, but will still terminate unhappily:

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");
   }
}