Gestionnaire d’exceptions global .NET dans l’application console

Question: Je souhaite définir un gestionnaire d’exceptions global pour les exceptions non gérées dans mon application console. En asp.net, on peut en définir un dans global.asax, et dans les applications / services Windows, on peut définir comme ci-dessous

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

Mais comment définir un gestionnaire d’exceptions global pour une application console?
currentDomain ne semble pas fonctionner (.NET 2.0)?

Modifier:

Argh, erreur stupide.
Dans VB.NET, il faut append le mot-clé “AddHandler” devant currentDomain, sinon on ne voit pas l’événement UnhandledException dans IntelliSense …
C’est parce que les compilateurs VB.NET et C # traitent différemment la gestion des événements.

Non, c’est la bonne façon de le faire. Cela a fonctionné exactement comme il se doit, quelque chose que vous pouvez travailler peut-être:

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

N’oubliez pas que vous ne pouvez pas intercepter les exceptions de chargement de type et de fichier générées par la gigue. Ils se produisent avant que votre méthode Main () ne démarre. Pour les récupérer, il faut retarder la gigue, déplacer le code risqué dans une autre méthode et lui appliquer l’atsortingbut [MethodImpl (MethodImplOptions.NoInlining)].

Si vous avez une application mono-thread, vous pouvez utiliser un simple try / catch dans la fonction Main, cependant, cela ne couvre pas les exceptions qui peuvent être lancées en dehors de la fonction Main, sur d’autres threads, par exemple (comme noté dans d’autres commentaires). Ce code montre comment une exception peut entraîner la fermeture de l’application même si vous avez essayé de la gérer dans Main (notez que le programme se termine normalement si vous appuyez sur Entrée et autorisez l’application à quitter normalement avant que l’exception ne se produise) , ça se termine malheureusement):

 static bool exiting = false; static void Main(ssortingng[] 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; } } 

Vous pouvez recevoir une notification lorsque un autre thread émet une exception pour effectuer un nettoyage avant la fermeture de l’application, mais pour autant que je sache, à partir d’une application console, vous ne pouvez pas forcer l’application à continuer si vous ne gérez pas l’exception sur le thread à partir duquel il est lancé sans utiliser certaines options de compatibilité obscures pour que l’application se comporte comme avec .NET 1.x. Ce code montre comment le thread principal peut être averti des exceptions provenant d’autres threads, mais se terminera malheureusement malheureusement:

 static bool exiting = false; static void Main(ssortingng[] 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; } } 

Donc, à mon avis, le moyen le plus propre de le gérer dans une application console est de s’assurer que chaque thread a un gestionnaire d’exceptions au niveau racine:

 static bool exiting = false; static void Main(ssortingng[] 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"); } } 

Vous devez également gérer les exceptions des threads:

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

Whoop, désolé que ce soit pour winforms, pour tous les threads que vous utilisez dans une application console, vous devrez inclure un bloc try / catch. Les threads d’arrière-plan qui rencontrent des exceptions non gérées ne provoquent pas la fin de l’application.

Ce que vous essayez devrait fonctionner selon le document MSDN pour .Net 2.0. Vous pouvez également essayer essayer directement sur votre point d’entrée pour l’application console.

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

Et maintenant votre prise va gérer tout ce qui n’a pas été capturé ( dans le thread principal ). Cela peut être gracieux et même redémarrer là où vous le vouliez, ou vous pouvez simplement laisser l’application mourir et enregistrer l’exception. Vous appendiez un dernier si vous vouliez faire un nettoyage. Chaque thread nécessitera sa propre gestion des exceptions de haut niveau similaire à la principale.

Édité pour clarifier le point concernant les threads comme indiqué par BlueMonkMN et montré en détail dans sa réponse.