77 votes

VS2010 n'affiche pas le message d'exception non géré dans une application WinForms sur une version 64 bits de Windows

Quand je crée un nouveau projet, j'ai eu un drôle de comportement pour unhandeled exceptions. C'est comment je peux reproduire le problème:

1) créer une nouvelle Application Windows Forms (C#, .NET Framework 4, VS2010)

2) ajoutez le code suivant au gestionnaire Form1_Load:

int vara = 5, varb = 0;
int varc = vara / varb;
int vard = 7;

Je m'attends à ce que VS les pauses et affiche un message d'exception non gérée à la deuxième ligne. Cependant, ce qui se passe est que la troisième ligne est tout simplement ignorée sans aucun message et l'application continue de fonctionner.

Je n'ai pas ce problème avec mes projets C#. Donc je suppose que mes nouveaux projets sont créés avec une étrange paramètres par défaut.

Quelqu'un aurait-il une idée de ce qui ne va pas avec mon projet???

J'ai essayé en cochant les cases en Debug->Exceptions. Mais alors exécutions pauses, même si j'ai la poignée de l'exception dans un bloc try-catch; qui n'est pas ce que je veux. Si je me souviens bien, il y avait une colonne appelée "les exceptions non gérées" ou quelque chose comme cela dans cette boîte de dialogue, qui ferait excatly ce que je veux. Mais dans mes projets, il y a une seule colonne ("Levée").

126voto

Hans Passant Points 475940

C'est un méchant problème induit par les Fenêtres wow64 couche d'émulation qui permet 32-bit de code à exécuter sur la version 64 bits de Windows. Il avale des exceptions dans le code qui déclenche l' Load événement. Prévenir le débogueur de les voir et de marcher dans. C'est apparemment difficile à corriger, les Fenêtres et les DevDiv groupes de Microsoft sont en pointant les doigts d'avant en arrière. DevDiv ne pouvez pas faire quoi que ce soit, Windows pense que c'est le comportement correct, mystérieusement en tant que sons. C'est seulement un problème avec un débogueur, votre code de la bombe comme d'habitude, sans que l'un.

Projet + Propriétés, onglet création, de changement de Plate-forme cible pour AnyCPU. Malheureusement désactive Edit + Continuer et peut ne pas toujours être possible que si vous avez une dépendance sur le code 32 bits.

D'autres solutions de contournement possibles:

  • Debug + Exceptions, cochez la Levée de la boîte pour le CLR exceptions.
  • Écrire try/catch dans l' Load de gestionnaire d'événements.
  • Utiliser Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException) dans la Main() méthode de sorte que l'exception piège dans la boucle de message n'est pas désactivé en mode de débogage. Ce paramètre permet cependant toutes les exceptions non gérées difficile à déboguer, l' ThreadException événement est assez inutile.
  • Considérez si votre code appartient vraiment dans l' Load de gestionnaire d'événements. Il est très rare d'en avoir besoin, cependant, il est populaire avec les programmeurs VB6 où Load était une grosse affaire. Vous avez seulement besoin d' Load lorsque vous êtes intéressé dans la taille de la fenêtre d'après les préférences de l'utilisateur et de mise à l'échelle automatique est appliquée. Tout le reste appartient au constructeur.
  • Mise à jour de Windows 8, il n'a pas ce problème.

Un bon d'écrire au sujet de ce problème est disponible dans ce blog.

10voto

Jonathon Reinhart Points 40535

Dans mon expérience, je ne vois que ce problème quand je suis en cours d'exécution avec un débogueur. L'application se comporte de la même lors de l'exécution autonome: l'exception n'est pas avalé.

Avec l'introduction de KB976038, vous pouvez faire ce travail que vous vous attendez à nouveau. Je n'ai jamais installé le correctif, donc je suis en supposant qu'il est venu dans le cadre de Win7 SP1.

Cela a été mentionné dans ce post:

Voici un code qui va activer le correctif logiciel:

public static class Kernel32
{
    public const uint PROCESS_CALLBACK_FILTER_ENABLED = 0x1;

    [DllImport("Kernel32.dll")]
    public static extern bool SetProcessUserModeExceptionPolicy(UInt32 dwFlags);

    [DllImport("Kernel32.dll")]
    public static extern bool GetProcessUserModeExceptionPolicy(out UInt32 lpFlags);


    public static void DisableUMCallbackFilter() {
        uint flags;
        GetProcessUserModeExceptionPolicy(out flags);

        flags &= ~PROCESS_CALLBACK_FILTER_ENABLED;
        SetProcessUserModeExceptionPolicy(flags);
    }
}

L'appeler au début de votre application:

    [STAThread]
    static void Main()
    {
        Kernel32.DisableUMCallbackFilter();

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

J'ai confirmé (avec l'exemple simple ci-dessous) que cela fonctionne, juste comme vous le souhaitez.

protected override void OnLoad(EventArgs e) {
    throw new Exception("BOOM");   // This will now get caught.
}

Donc, ce que je ne comprends pas, c'est pourquoi il était auparavant impossible pour le débogueur poignée de passage en mode noyau de la pile des cadres, mais avec ce correctif, ils en quelque sorte pensé à elle.

1voto

Gabe Halsmer Points 303

Je suis en utilisant WPF et rencontré ce même problème. J'avais essayé de Hans 1-3 suggestions déjà, mais ne les aimais pas parce que le studio ne s'arrête pas à l'endroit où l'erreur a été (donc je ne pouvais pas afficher mes variables et de voir quel était le problème).

J'ai donc essayé de Hans 4e suggestion. J'ai été étonné à la façon dont une grande partie de mon code pourrait être déplacé dans la MainWindow constructeur sans aucun problème. Je ne sais pas pourquoi j'ai eu l'habitude de mettre autant de logique dans l'événement Load, mais apparemment, beaucoup de ce qui peut être fait dans le ctor.

Cependant, cela a eu le même problème que 1-3. Les erreurs qui se produisent au cours de la ctor pour WPF obtenir enveloppé dans un générique Xaml exception. (une exception interne a l'erreur réelle, mais encore une fois j'ai voulu studio à juste briser les ennuis).

Ce qui a fini par travailler pour moi a été de créer un thread, le sommeil 50ms, la répartition de thread principal et de faire ce dont j'ai besoin...

    void Window_Loaded(object sender, RoutedEventArgs e)
    {
        new Thread(() =>
        {
            Thread.Sleep(50);
            CrossThread(() => { OnWindowLoaded(); });
        }).Start();
    }
    void CrossThread(Action a)
    {
        this.Dispatcher.BeginInvoke(a);
    }
    void OnWindowLoaded()
    {
        ...do my thing...

De cette façon, studio pause où un uncaught exception se produit.

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