94 votes

Comment puis-je faire quelque chose qui attrape toutes les exceptions non gérées dans une application WinForms ?

Jusqu'à présent, je mettais simplement un bloc try/catch autour de l'élément Application.Run dans le Program.cs point d'entrée du programme. Cela permet d'attraper 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. J'obtiens la boîte d'exception non gérée.

Je ne veux pas que cela se produise. Je veux que toutes les exceptions soient capturées lorsque le programme est exécuté en mode non-débogage. Le programme a plusieurs threads et il est préférable que toutes les exceptions soient capturées par le même gestionnaire ; je veux enregistrer les exceptions dans la base de données. Je veux enregistrer les exceptions dans la base de données. Quelqu'un a-t-il des conseils à me donner sur la façon de procéder ?

0 votes

Mais pas en double : stackoverflow.com/q/150544/345659

130voto

Can Gencer Points 4644

Regardez l'exemple de la page Documentation sur les exceptions de threads :

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 souhaiter ne pas attraper d'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'attraper les exceptions lors du débogage.

EDIT : Une autre façon de vérifier l'exécution de votre application dans un débogueur, plus propre que la vérification d'un nom de fichier.

(voir les commentaires de moltenform, Kiquenet et Doug)

if(!System.Diagnostics.Debugger.IsAttached) { ... }

Cela permet d'éviter le problème de l'utilisation d'un débogueur différent de celui du vshost.exe .

1 votes

J'ai créé un travailleur en arrière-plan, et dans le gestionnaire d'événement dowork, j'ai intentionnellement provoqué une exception de référence nulle. Cependant, cette exception n'a pas été détectée par AppDomain.CurrentDomain.UnhandledException en dépit de la configuration de ces éléments : Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException) ; Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException) ; AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException) ;

5 votes

@IsaacB, le travailleur en arrière-plan attrape lui-même les exceptions. Vous pouvez vérifier l'exception dans l'événement RunWorkerCompleted, en regardant la propriété RunCompletedEventArgs.Error.

1 votes

Vous pouvez tester la gestion des exceptions pour des threads supplémentaires en plaçant ceci dans le OnLoad de votre formulaire principal. new Thread(() => { throw new Exception() ; }).Start() ;

27voto

Carlos P Points 1625

Dans NET 4, certaines exceptions sont ne sont plus prises en compte par défaut ; il s'agit généralement d'exceptions qui indiquent un état corrompu (éventuellement fatal) de l'exécutable, comme une exception de violation d'accès.

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

0 votes

Puis-je utiliser AppDomain.CurrentDomain.UnhandledException y Application.ThreadException également avec [HandleProcessCorruptedStateExceptions] tag ?

22voto

Seb Points 729

Un bon exemple se trouve à l'adresse suivante http://www.csharp-examples.net/catching-unhandled-exceptions/ En gros, 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");
    }

9voto

Teoman Soygul Points 17544

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

NBug.Settings.Destination1 = "Type=Mail;From=me@mycompany.com;To=bugtracker@mycompany.com;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 gérés dans votre application, même lorsqu'elle est déployée auprès des clients. Si vous ne souhaitez pas utiliser une bibliothèque tierce, vous devriez 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());

1 votes

Il n'y a pas de quoi. Utilisez le forum de discussion du projet NBug si vous avez d'autres questions ( nbusy.com/forum/f11 ) ou utilisez la balise [nbug] ici.

0 votes

Bien entendu, vous pouvez également abonner un gestionnaire d'événements "normal" à l'événement UnhandledException. Voir msdn.microsoft.com/en-us/library/

0 votes

Sur Win7 + VS10, si je m'abonne à ces événements, l'abonnement ne s'exécute pas, mais la boîte de dialogue habituelle de Windows Vista/7 s'affiche. Check Online for a Solution Ou Close the Program etc. Mais si je ne m'abonne PAS, j'obtiens la fenêtre d'exception générique .NET non gérée. Cela se produit à la fois sur les versions Release et Debug, et j'ai également essayé d'utiliser le paramètre Application.SetUnhandledExceptionMode(UnhandledExceptionMode‌​.CatchException); Cela ne change rien.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X