web-dev-qa-db-fra.com

Comment puis-je créer quelque chose qui intercepte toutes les exceptions «non gérées» dans une application WinForms?

Jusqu'à présent, je viens de mettre un bloc try/catch autour du Application.Run dans le Program.cs point d'entrée du programme. Cela intercepte assez bien toutes les exceptions en mode débogage, mais lorsque j'exécute le programme sans le mode débogage, les exceptions ne sont plus gérées. Je reçois la boîte d'exception non gérée.

Je ne veux pas que cela se produise. Je veux que toutes les exceptions soient interceptées lors de l'exécution en mode non débogage. Le programme a plusieurs threads et de préférence toutes les exceptions sont capturées par le même gestionnaire; Je souhaite consigner les exceptions dans la base de données. Quelqu'un a-t-il des conseils sur la façon de procéder?

79
Isaac Bolinger

Jetez un œil à l'exemple de la documentation ThreadException :

public static void Main(string[] args)
{
   // Add the event handler for handling UI thread exceptions to the event.
    Application.ThreadException += new     
  ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);

  // Set the unhandled exception mode to force all Windows Forms errors
  // to go through our handler.
  Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

  // Add the event handler for handling non-UI thread exceptions to the event. 
  AppDomain.CurrentDomain.UnhandledException += new       
  UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}

Vous pouvez également ne pas intercepter les exceptions lors du débogage, car cela facilite le débogage. C'est un peu un hack, mais pour cela, vous pouvez envelopper le code ci-dessus avec

 if (!AppDomain.CurrentDomain.FriendlyName.EndsWith("vshost.exe")) { ... }

Pour éviter d'intercepter les exceptions lors du débogage.

102
Can Gencer

Dans NET 4, certaines exceptions sont ne sont plus interceptées par défaut; il s'agit généralement d'exceptions qui indiquent un état corrompu (éventuellement fatal) de l'exécutable, comme une AccessViolationException.

Essayez d'utiliser la balise [HandleProcessCorruptedStateExceptions] devant votre méthode principale, par exemple.

using System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions

[HandleProcessCorruptedStateExceptions]
public static int Main()
{
    try
    {
        // Catch any exceptions leaking out of the program
        CallMainProgramLoop();
    }
    catch (Exception e) // We could be catching anything here
    {
        System.Console.WriteLine(e.Message);
        return 1;
    }
    return 0;
  } 
27
Carlos P

Un bel exemple peut être trouvé à http://www.csharp-examples.net/catching-unhandled-exceptions/ Fondamentalement, changez votre principal en:

static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

        Application.Run(new Form1());
    }

    static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
    {
        MessageBox.Show(e.Exception.Message, "Unhandled Thread Exception");
    }

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        MessageBox.Show((e.ExceptionObject as Exception).Message, "Unhandled UI Exception");
    }
17
Seb

Vous pouvez utiliser la bibliothèque NBug pour cela. Avec une configuration minimale comme celle-ci:

NBug.Settings.Destination1 = "Type=Mail;[email protected];[email protected];SmtpServer=smtp.mycompany.com;";
AppDomain.CurrentDomain.UnhandledException += NBug.Handler.UnhandledException;
Application.ThreadException += NBug.Handler.ThreadException;

Vous pouvez commencer à collecter des informations sur tous les bogues non traités dans votre application, même lorsqu'elle est déployée sur les clients. Si vous ne souhaitez pas utiliser une bibliothèque tierce, vous devez vous attacher aux événements ci-dessous:

// These two should come before enabling visual styles or running the application
AppDomain.CurrentDomain.UnhandledException += ...
Application.ThreadException += ...
...
Application.Run(new Form1());
8
Teoman Soygul