Wenn ich ein neues Projekt erstelle, tritt bei nicht behandelten Ausnahmen ein seltsames Verhalten auf. So kann ich das Problem reproduzieren:
1) Erstellen Sie eine neue Windows Forms-Anwendung (C #, .NET Framework 4, VS2010).
2) Fügen Sie dem Form1_Load
Handler den folgenden Code hinzu :
int vara = 5, varb = 0;
int varc = vara / varb;
int vard = 7;
Ich würde erwarten, dass VS in der zweiten Zeile unterbrochen wird und eine nicht behandelte Ausnahmemeldung anzeigt. Was jedoch passiert, ist, dass die dritte Zeile nur ohne Nachricht übersprungen wird und die Anwendung weiter ausgeführt wird.
Ich habe dieses Problem mit meinen vorhandenen C # -Projekten nicht. Ich denke also, dass meine neuen Projekte mit einigen seltsamen Standardeinstellungen erstellt werden.
Hat jemand eine Idee was mit meinem Projekt los ist ???
Ich habe versucht, die Kontrollkästchen unter Debug-> Ausnahmen zu aktivieren. Aber dann bricht die Ausführung ab, wenn ich die Ausnahme in einem try-catch
Block behandle. das ist auch nicht was ich will. Wenn ich mich richtig erinnere, gab es in diesem Dialogfeld eine Spalte mit dem Namen "nicht behandelte Ausnahmen" oder ähnliches, die genau das tun würde, was ich will. In meinen Projekten gibt es jedoch nur eine Spalte ("Thrown").
quelle
Antworten:
Dies ist ein unangenehmes Problem, das durch die wow64-Emulationsschicht verursacht wird, mit der 32-Bit-Code unter der 64-Bit-Version von Windows 7 ausgeführt werden kann. Es werden Ausnahmen im Code verschluckt, der als Reaktion auf eine vom 64-Bit-Fenstermanager generierte Benachrichtigung ausgeführt wird , wie die
Load
Veranstaltung. Verhindern, dass der Debugger ihn sieht und eingreift. Dieses Problem ist schwer zu beheben. Die Windows- und DevDiv-Gruppen bei Microsoft zeigen mit den Fingern hin und her. DevDiv kann nichts dagegen tun, Windows hält es für das richtige und dokumentierte Verhalten, so mysteriös das klingt.Es ist sicherlich dokumentiert, aber fast niemand versteht die Konsequenzen oder hält es für vernünftiges Verhalten. Vor allem nicht, wenn die Fensterprozedur natürlich nicht sichtbar ist, wie in jedem Projekt, das Wrapper-Klassen verwendet, um die Fensterinstallation auszublenden. Wie jede Winforms, WPF oder MFC App. Das zugrunde liegende Problem ist, dass Microsoft nicht herausfinden konnte, wie Ausnahmen vom 32-Bit-Code zurück zum 64-Bit-Code geleitet werden, der die Benachrichtigung zurück zum 32-Bit-Code ausgelöst hat, der versucht, die Ausnahme zu behandeln oder zu debuggen.
Es ist nur ein Problem mit einem angehängten Debugger, Ihr Code wird wie gewohnt ohne einen bombardieren.
Projekt> Eigenschaften> Registerkarte Erstellen> Plattformziel = AnyCPU und deaktivieren Sie Bevorzugt 32-Bit. Ihre App wird jetzt als 64-Bit-Prozess ausgeführt, wodurch der Wow64-Fehlermodus beseitigt wird. Einige Konsequenzen: Deaktivieren Sie Bearbeiten + Fortfahren für VS-Versionen vor VS2013 und ist möglicherweise nicht immer möglich, wenn Sie von 32-Bit-Code abhängig sind.
Andere mögliche Problemumgehungen:
Load
Ereignisbehandlungsroutine und failfast in den catch-Block.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException)
in demMain()
Verfahren so , dass der Ausnahme - Trap in der Nachrichtenschleife nicht im Debug - Modus deaktiviert. Dies macht es jedoch schwierig, alle nicht behandelten Ausnahmen zu debuggen. DasThreadException
Ereignis ist ziemlich nutzlos.Load
Ereignisbehandlungsroutine gehört . Es wird sehr selten benötigt, ist jedoch in VB.NET und einem Schwanenlied sehr beliebt, da es sich um das Standardereignis handelt und ein Doppelklick den Ereignishandler trivial hinzufügt. Sie benötigen nur dann wirklich,Load
wenn Sie an der tatsächlichen Fenstergröße interessiert sind, nachdem Benutzereinstellungen und automatische Skalierung angewendet wurden. Alles andere gehört in den Konstruktor.quelle
Application.ThreadException
. Das Einstellen scheint zu helfen - die Ausnahmen werden in der IDE und vom Debugger ausgelöst.Nach meiner Erfahrung wird dieses Problem nur angezeigt, wenn ein Debugger angeschlossen ist. Die Anwendung verhält sich im Standalone-Modus genauso: Die Ausnahme wird nicht verschluckt.
Mit der Einführung von KB976038 können Sie diese Funktion wieder wie erwartet ausführen . Ich habe den Hotfix nie installiert, daher gehe ich davon aus, dass er Teil von Win7 SP1 ist.
Dies wurde in diesem Beitrag erwähnt:
Hier ist ein Code, der den Hotfix aktiviert:
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); } }
Nennen Sie es zu Beginn Ihrer Bewerbung:
[STAThread] static void Main() { Kernel32.DisableUMCallbackFilter(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); }
Ich habe bestätigt (mit dem einfachen Beispiel unten), dass dies genau so funktioniert, wie Sie es erwarten würden.
protected override void OnLoad(EventArgs e) { throw new Exception("BOOM"); // This will now get caught. }
Was ich nicht verstehe, ist, warum es dem Debugger bisher unmöglich war, überkreuzende Kernel-Modus-Stack-Frames zu verarbeiten, aber mit diesem Hotfix haben sie es irgendwie herausgefunden.
quelle
Set/GetProcessUserModeExceptionPolicy
sind immer noch nicht auf MSDN dokumentiert und Kernel32.dll von Windows 8 exportiert sie nicht.Kompilieren Sie, wie Hans erwähnt, die Anwendung und führen Sie die Exe ohne angehängten Debugger aus.
Für mich bestand das Problem darin, einen Klasseneigenschaftsnamen zu ändern, an den ein BindingSource-Steuerelement gebunden war. Ohne IDE konnte ich den Fehler sehen:
Das Problem wurde behoben, indem das BindingSource-Steuerelement so repariert wurde, dass es an den aktualisierten Eigenschaftsnamen gebunden wurde:
quelle
Ich benutze WPF und bin auf dasselbe Problem gestoßen. Ich hatte bereits Hans 1-3-Vorschläge ausprobiert, mochte sie aber nicht, weil das Studio nicht dort anhielt, wo der Fehler lag (daher konnte ich meine Variablen nicht anzeigen und das Problem erkennen).
Also habe ich Hans '4. Vorschlag ausprobiert. Ich war überrascht, wie viel von meinem Code ohne Probleme in den MainWindow-Konstruktor verschoben werden konnte. Ich bin mir nicht sicher, warum ich es mir zur Gewohnheit gemacht habe, so viel Logik in das Load-Ereignis zu integrieren, aber anscheinend kann viel davon im ctor erledigt werden.
Dies hatte jedoch das gleiche Problem wie 1-3. Fehler, die während des ctor für WPF auftreten, werden in eine generische Xaml-Ausnahme eingeschlossen. (Eine innere Ausnahme hat den wirklichen Fehler, aber ich wollte wieder, dass das Studio nur an der eigentlichen Problemstelle kaputt geht).
Am Ende arbeitete ich für mich, um einen Thread zu erstellen, 50 ms zu schlafen, zum Haupt-Thread zurückzukehren und das zu tun, was ich brauche ...
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...
Auf diese Weise würde das Studio genau dort brechen, wo eine nicht erfasste Ausnahme auftritt.
quelle
Eine einfache Problemumgehung könnte sein, wenn Sie Ihren Init-Code in ein anderes Ereignis verschieben können, wie es
Form_Shown
später aufgerufen wurdeForm_Load
, und ein Flag verwenden, um den Startcode in der ersten angezeigten Form auszuführen:bool firstLoad = true; //flag to detect first form_shown private void Form1_Load(object sender, EventArgs e) { //firstLoad = true; //dowork(); //not execute initialization code here (postpone it to form_shown) } private void Form1_Shown(object sender, EventArgs e) { if (firstLoad) //simulate Form-Load { firstLoad = false; dowork(); } } void dowork() { var f = File.OpenRead(@"D:\NoSuchFile756.123"); //this cause an exception! }
quelle