Comment implémenter un gestionnaire d’exception “catch’em all” avec resume?

Je me demande comment puis-je écrire un gestionnaire d’exception catch’em all au niveau de l’application qui donnera à l’utilisateur la possibilité de reprendre le stream d’application?

Si vous exécutez une application Windows Forms: ajoutez un gestionnaire à l’événement Application.ThreadException .

Je suppose que vous écrivez une application Windows, auquel cas, vous pouvez le faire. Je laisserai les droits et les torts de savoir si vous devriez ou non à d’autres. Il existe déjà suffisamment de réponses à ce sujet et je vous suggère de les examiner attentivement avant de le faire .

Notez que ce code se comportera différemment dans le débogueur que si vous exécutez l’application directement (une autre raison de ne pas le faire peut-être). Pour que l’application affiche la boîte de message et continue ensuite, vous devez l’exécuter à partir de l’explorateur et non de visual studio.

Créez une nouvelle application Windows Forms. Le code dans Program.cs ressemble à ceci:

 using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Windows.Forms; namespace WindowsFormsApplication2 { static class Program { ///  /// The main entry point for the application. ///  [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Form1 form1 = new Form1(); Application.ThreadException += new ThreadExceptionEventHandler(form1.UnhandledThreadExceptionHandler); Application.Run(form1); } } } 

Ensuite, faites en sorte que le code dans Form1 ressemble à ceci:

 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Windows.Forms; namespace WindowsFormsApplication2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } public void UnhandledThreadExceptionHandler(object sender, ThreadExceptionEventArgs e) { this.HandleUnhandledException(e.Exception); } public void HandleUnhandledException(Exception e) { // do what you want here. if (MessageBox.Show("An unexpected error has occurred. Continue?", "My application", MessageBoxButtons.YesNo, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button2) == DialogResult.No) { Application.Exit(); } } private void button1_Click(object sender, EventArgs e) { throw new ApplicationException("Exception"); } } } 

(Ajoutez button1 au formulaire et attachez-le button1_Cliquez.)

Cela dépend de ce que vous entendez par “reprendre”. Le problème avec les exceptions est que, sauf si vous êtes très prudent, au moment où une exception se produit, l’état de votre application est probablement corrompu – vous avez peut-être terminé la moitié d’ une opération.

Si vous pouvez isoler vos opérations – un peu comme une firebase database isole des transactions -, vous pouvez alors laisser votre utilisateur reprendre à partir du “dernier sharepoint validation”. Cela dépendra beaucoup du type de votre application. Pourriez-vous nous donner plus de détails sur le type d’application que vous construisez?

Utilisez le code ci-dessous dans votre classe program.cs. Il enverra automatiquement le courrier quand une exception se produira.

 using System; using System.Windows.Forms; using System.Net; using System.Net.Mail; using System.Threading; namespace ExceptionHandlerTest { static class Program { ///  /// The main entry point for the application. ///  [STAThread] static void Main() { Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException); // Your designer generated commands. } static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) { var fromAddress = new MailAddress("your Gmail address", "Your name"); var toAddress = new MailAddress("email address where you want to receive reports", "Your name"); const ssortingng fromPassword = "your password"; const ssortingng subject = "exception report"; Exception exception = e.Exception; ssortingng body = exception.Message + "\n" + exception.Data + "\n" + exception.StackTrace + "\n" + exception.Source; var smtp = new SmtpClient { Host = "smtp.gmail.com", Port = 587, EnableSsl = true, DeliveryMethod = SmtpDeliveryMethod.Network, UseDefaultCredentials = false, Credentials = new NetworkCredential(fromAddress.Address, fromPassword) }; using (var message = new MailMessage(fromAddress, toAddress) { Subject = subject, Body = body }) { //You can also use SendAsync method instead of Send so your application begin invoking instead of waiting for send mail to complete. SendAsync(MailMessage, Object) :- Sends the specified e-mail message to an SMTP server for delivery. This method does not block the calling thread and allows the caller to pass an object to the method that is invoked when the operation completes. smtp.Send(message); } } } } 

Je ne pense pas que ce soit vraiment faisable en utilisant un gestionnaire d’erreur global. Vous devez déterminer quels types d’erreurs sont récupérables à différents moments de votre application et écrire des gestionnaires d’erreurs spécifiques pour les traiter dès qu’ils se produisent – à moins que vous ne souhaitiez recourir au redémarrage de l’application. L’erreur réelle est. Pour faire n’importe quel type de CV, vous devez enregistrer suffisamment d’état pour pouvoir redémarrer à partir d’un bon état connu.

Vous devriez lire tous les problèmes associés au style de traitement des erreurs ” On Error Resume Next ” de VB. On dirait que vous essayez d’implémenter ceci pour C #.

Même si vous pouvez reprendre à partir du moment où l’exception est générée, il s’agit d’une technique cassée pour la gestion des erreurs. Il n’y a aucun moyen pour un gestionnaire global de pouvoir réellement gérer une erreur / exception – il ne peut pas savoir ce qui est requirejs pour une situation arbitraire.

Vous devez définir une sorte de variable globale et faire en sorte que le code de ligne principale la vérifie en permanence pour détecter les indications d’erreur (c’est-à-dire, utilisez la technique VB).

Je pense que le mieux que vous puissiez faire pour remédier à une erreur telle que celle que vous décrivez consiste à intercepter l’exception au niveau de l’application, à consigner le problème, à informer l’utilisateur (et éventuellement à générer / envoyer un rapport de problème pour vous), et redémarrez l’application. Bien sûr, si vous attrapez l’exception plus près du problème, ce gestionnaire a la possibilité de faire quelque chose d’un peu plus intelligent. Vous ne devez donc pas vous fier au gestionnaire au niveau de l’application comme une béquille, mais simplement comme une solution de sécurité.

Dans certaines versions de .NET, vous pouvez réellement placer un capteur autour de Application.Run () (vous le trouverez dans program.cs), ce qui devrait permettre de saisir toutes les exceptions du thread principal. Cependant, dans la plupart des cas, cette conception peut être médiocre vous beaucoup une occasion de “reprendre”. De plus, vous devrez toujours gérer manuellement les exceptions sur les threads d’arrière-plan.

Vous pouvez concevoir une application pour “attraper tout” et afficher un message d’erreur commun et des informations de débogage, c’est bien tant que vous quittez par la suite. Ce qui est fortement déconseillé, c’est de mettre à la disposition de l’utilisateur un «curriculum vitae», qui risque de vous poser davantage de problèmes à long terme.

Cela crie juste mauvaise conception partout. Ne jamais utiliser des exceptions pour des choses comme ça. Les exceptions ne doivent être utilisées que lorsque quelque chose que le programmeur n’avait pas l’intention de se produire.

Si vous voulez gérer les erreurs. n’utilisez pas d’exceptions comme celle-ci, rahter construisez un système dans lequel vous sauvegardez des états et pouvez revenir aux états, etc., mais en utilisant des exceptions pour la gestion des états, mauvaise idée.

Le bloc d’application Gestion des exceptions de Microsoft Enterprise Library contient des exemples illustrant cette procédure.

En gros, vous entourez le code qui peut générer des exceptions avec ceci:

 try { MyMethodThatMightThrow(); } catch(Exception ex) { bool rethrow = ExceptionPolicy.HandleException(ex, "SomePolicy"); if (rethrow) throw; } 

Vous pouvez ensuite configurer la stratégie pour afficher une boîte de dialog à l’utilisateur et lui demander si elle souhaite continuer.

Vous devez toujours insérer des blocs catch dans votre code aux endroits où vous pensez être dans un état cohérent.