C’est quelque chose que j’ai découvert il ya quelques jours à peine, j’ai la confirmation que cela ne se limite pas à ma machine de cette question .
Le moyen le plus simple de le reproduire consiste à démarrer une application Windows Forms, à ajouter un bouton et à écrire le code suivant:
private void button1_Click(object sender, EventArgs e) {
MessageBox.Show("yada");
Environment.Exit(1); // Kaboom!
}
Le programme échoue après l'exécution de l'instruction Exit (). Sous Windows Forms, vous obtenez "Erreur lors de la création du descripteur de fenêtre".
L'activation du débogage non géré permet de mieux comprendre ce qui se passe. La boucle COM modal est en cours d'exécution et permet à un message WM_Paint d'être remis. C'est fatal sur une forme éliminée.
Les seuls faits que j'ai recueillis jusqu'à présent sont les suivants:
Je suis particulièrement intéressé par ce que vous pourriez éventuellement faire pour éviter ce crash. Le scénario AppDomain.UnhandledException me stoppe particulièrement; il n'y a pas beaucoup de façons de terminer un programme .NET. Veuillez noter que les appels Application.Exit () ou Form.Close () ne sont pas valides dans un gestionnaire d'événements pour UnhandledException. Ils ne constituent donc pas des solutions de contournement.
MISE À JOUR: Mehrdad a souligné que le thread du finaliseur pourrait faire partie du problème. Je pense que je vois cela et que je vois également des preuves pour le délai d'expiration de 2 secondes que le CLR donne le fil d'exécution au finaliseur pour terminer l'exécution.
Le finaliseur est à l'intérieur de NativeWindow.ForceExitMessageLoop (). Il existe une fonction IsWindow () Win32 qui correspond approximativement à l'emplacement du code, avec un décalage de 0x3c lorsque vous examinez le code machine en mode 32 bits. Il semble que IsWindow () est une impasse. Je ne peux pas obtenir une bonne trace de pile pour les internes, cependant, le débogueur pense que l'appel P/Invoke vient de revenir. C'est difficile à expliquer. Si vous pouvez obtenir une meilleure trace de pile, j'aimerais bien la voir. Mien:
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.ForceExitMessageLoop() + 0x3c bytes
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Finalize() + 0x16 bytes
[Native to Managed Transition]
kernel32.dll!@BaseThreadInitThunk@12() + 0xe bytes
ntdll.dll!___RtlUserThreadStart@8() + 0x27 bytes
ntdll.dll!__RtlUserThreadStart@8() + 0x1b bytes
Rien de plus que l'appel ForceExitMessageLoop, le débogueur non géré activé.
J'ai contacté Microsoft à propos de ce problème et cela semblait avoir porté ses fruits. Au moins, j'aimerais penser que c'était le cas :). Bien que je n'ai pas reçu de confirmation de la résolution de leur part, le groupe Windows est difficile à contacter directement et j'ai dû utiliser un intermédiaire.
Une mise à jour fournie via Windows Update a résolu le problème. Le délai visible de 2 secondes avant le crash n'est plus présent, ce qui suggère fortement que le blocage de IsWindow () a été résolu. Et le programme s'arrête proprement et de manière fiable. La mise à jour des correctifs installés pour Windows Defender, wdboot.sys, wdfilter.sys, tcpip.sys, rpcrt4.dll, uxtheme.dll, crypt32.dll et wintrust.dll
Uxtheme.dll est l'intrus. Il implémente l'API de thématisation Visual Styles et est utilisé par ce programme de test. Je ne peux pas être sûr, mais mon argent est sur celui-ci en tant que source du problème. La copie dans C:\WINDOWS\system32 a le numéro de version 6.2.9200.16660, créé le 14 août 2013 sur ma machine.
Affaire classée.
Je ne sais pas pourquoi cela ne fonctionne pas "plus jamais" , mais je pense que Environment.Exit
exécute les finaliseurs en attente. Environment.FailFast
non.
Il se peut que (pour une raison étrange) vous ayez des finaliseurs en suspens qui doivent être exécutés par la suite, pour que cela se produise.
Cela n'explique pas pourquoi cela se produit, mais je n'appellerais pas Environment.Exit
dans un gestionnaire d'événements de boutons comme votre exemple - fermez plutôt le formulaire principal comme suggéré dans la réponse de rene .
En ce qui concerne un gestionnaire AppDomain.UnhandledException
, vous pourriez peut-être simplement définir Environment.ExitCode
plutôt que d'appeler Environment.Exit
.
Je ne suis pas sûr de ce que vous essayez d'atteindre ici. Pourquoi voulez-vous renvoyer un code de sortie à partir d'une application Windows Forms? Normalement, les codes de sortie sont utilisés par les applications de la console.
Je suis particulièrement intéressé par ce que vous pourriez faire pour éviter ce crash L'appel de Environment.Exit () est requis pour empêcher la boîte de dialogue WER de s'afficher.
Avez-vous un essai/attraper dans la méthode principale? Pour les applications Windows Forms, j'ai toujours une boucle try/catch autour de la boucle de message, ainsi que des gestionnaires d'exceptions non gérés.
J'ai trouvé le même problème dans notre application, nous l'avons résolu avec la construction suivante:
Environment.ExitCode=1;
Application.Exit();