C'est quelque chose que j'ai découvert il y a quelques jours à peine, j'ai eu la confirmation que cette question ne se limitait pas à ma machine .
Le moyen le plus simple de le reproduire est de démarrer une application Windows Forms, d'ajouter un bouton et d'écrire ce code:
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 (). Sur Windows Forms, vous obtenez "Erreur lors de la création de la poignée de fenêtre".
L'activation du débogage non géré montre quelque peu ce qui se passe. La boucle modale COM est en cours d'exécution et permet la remise d'un message WM_PAINT. C'est fatal sur une forme éliminée.
Les seuls faits que j'ai recueillis jusqu'à présent sont:
- Ce n'est pas seulement limité à l'exécution avec le débogueur. Cela échoue également sans un. Plutôt mal aussi, la boîte de dialogue de crash WER apparaît deux fois .
- Cela n'a rien à voir avec le bitness du processus. La couche wow64 est assez notoire, mais une construction AnyCPU plante de la même manière.
- Cela n'a rien à voir avec la version .NET, 4.5 et 3.5 plantent de la même manière.
- Le code de sortie n'a pas d'importance.
- L'appel de Thread.Sleep () avant d'appeler Exit () ne résout pas le problème.
- Cela se produit sur la version 64 bits de Windows 8 et Windows 7 ne semble pas être affecté de la même manière.
- Cela devrait être un comportement relativement nouveau, je n'ai jamais vu cela auparavant. Je ne vois aucune mise à jour pertinente fournie via Windows Update , même si l'historique des mises à jour n'est plus précis sur ma machine.
- C'est un comportement extrêmement cassant. Vous écririez du code comme celui-ci dans un gestionnaire d'événements pour AppDomain.UnhandledException, et il se bloque de la même manière.
Je suis particulièrement intéressé par ce que vous pourriez faire pour éviter ce crash. En particulier, le scénario AppDomain.UnhandledException me laisse perplexe; il n'y a pas beaucoup de façons de terminer un programme .NET. Veuillez noter que l'appel à Application.Exit () ou Form.Close () ne sont pas valides dans un gestionnaire d'événements pour UnhandledException, ils ne sont donc pas des solutions de contournement.
MISE À JOUR: Mehrdad a souligné que le fil de finalisation pourrait faire partie du problème. Je pense que je vois cela et que je vois également des preuves pour le délai de 2 secondes que le CLR donne au thread de finalisation pour terminer l'exécution.
Le finaliseur est dans NativeWindow.ForceExitMessageLoop (). Il y a là une fonction IsWindow () Win32 qui correspond à peu près à l'emplacement du code, offset 0x3c lorsque vous regardez le code machine en mode 32 bits. Il semble que IsWindow () est dans une impasse. Je ne peux pas obtenir une bonne trace de pile pour les éléments 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'adorerais 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 au-dessus de l'appel ForceExitMessageLoop, débogueur non géré activé.
This happens on the 64-bit version of Windows 8
Hans l'a dit!Exit(0)
un peu avec un Win7 64 bits, ChangerExitCode
n'aide pas maintenant à utiliserProcess.GetCurrentProcess().Kill()
sans aucun problème cela fonctionneRéponses:
J'ai contacté Microsoft à propos de ce problème et cela semble avoir porté ses fruits. Au moins j'aimerais penser que oui :). Bien que je n'ai pas reçu de confirmation d'une 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 notable de 2 secondes avant le crash n'est plus présent, suggérant fortement que l'impasse IsWindow () a été résolue. Et le programme s'arrête proprement et de manière fiable. La mise à jour a installé les correctifs pour Windows Defender, wdboot.sys, wdfilter.sys, tcpip.sys, rpcrt4.dll, uxtheme.dll, crypt32.dll et wintrust.dll
Uxtheme.dll est un canard étrange. Il implémente l'API de thématisation des styles visuels et est utilisé par ce programme de test. Je ne peux pas en être sûr, mais mon argent est sur celui-là comme 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.
la source
Je ne sais pas pourquoi cela ne fonctionne "plus" , mais je pense qu'il
Environment.Exit
exécute les finaliseurs en attente.Environment.FailFast
pas.Il se peut que (pour une raison étrange) vous ayez d'étranges finaliseurs en attente qui doivent être exécutés par la suite, ce qui provoque ce problème.
la source
NativeWindow.ForceExitMessageLoop
rester bloqué dans du code géré ou non géré? Est-il même bloqué, ou est-il occupé à attendre ou à attendre un message ou autre chose?Cela n'explique pas pourquoi cela se produit, mais je n'appellerais pas
Environment.Exit
un gestionnaire d'événements de bouton comme votre exemple - fermez plutôt le formulaire principal comme suggéré dans la réponse de rene .En ce qui concerne un
AppDomain.UnhandledException
gestionnaire, vous pourriez peut-être simplement définirEnvironment.ExitCode
plutôt que d'appelerEnvironment.Exit
.Je ne suis pas sûr de ce que vous essayez de réaliser ici. Pourquoi souhaitez-vous renvoyer un code de sortie à partir d'une application Windows Forms? Normalement, les codes de sortie sont utilisés par les applications de console.
Avez-vous un essai / capture dans la méthode Main? Pour les applications Windows Forms, j'ai toujours un try / catch autour de la boucle de message ainsi que les gestionnaires d'exceptions non gérés.
la source
Application.Exit
au lieu deEnvironment.Exit
.J'ai trouvé le même problème dans notre application, nous l'avons résolu avec la construction suivante:
la source