none
Sporadisch auftretender Fehler RRS feed

  • Frage

  • Hallo zusammen,

    Ich habe ein Problem mit einem sporadisch auftretendem Fehler, den ich so leider nicht reproduzieren kann, der mir aber immer mal von Usern zugeschickt wird. Leider kann ich mit der Fehlermeldung nicht viel anfangen:

    ************** Ausnahmetext **************

    System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.

       bei LMVerwaltung.FrmLMBeleg.positionSpeichern()

       bei LMVerwaltung.FrmLMBeleg.FrmLMBeleg_KeyDown(Object sender, KeyEventArgs e)

       bei System.Windows.Forms.Control.OnKeyDown(KeyEventArgs e)

       bei System.Windows.Forms.Control.ProcessKeyEventArgs(Message& m)

       bei System.Windows.Forms.Form.ProcessKeyPreview(Message& m)

       bei System.Windows.Forms.Control.ProcessKeyPreview(Message& m)

       bei System.Windows.Forms.Control.ProcessKeyPreview(Message& m)

       bei System.Windows.Forms.Control.ProcessKeyPreview(Message& m)

       bei System.Windows.Forms.DataGridView.ProcessKeyPreview(Message& m)

       bei System.Windows.Forms.Control.ProcessKeyPreview(Message& m)

       bei System.Windows.Forms.Control.ProcessKeyMessage(Message& m)

       bei System.Windows.Forms.Control.WmKeyChar(Message& m)

       bei System.Windows.Forms.Control.WndProc(Message& m)

       bei System.Windows.Forms.TextBoxBase.WndProc(Message& m)

       bei System.Windows.Forms.TextBox.WndProc(Message& m)

       bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)

       bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)

       bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

    Kann irgendjemand etwas mit dieser Fehlermeldung anfangen?
    Donnerstag, 8. Januar 2015 07:50

Antworten

  • Hallo,
    Methoden, die 600 Zeilen lang sind, sind eine schlechte Wahl. Versuche diese in mehr Methoden aufzugliedern, damit eben Dinge wie das Debuggen leichter werden.

    Sonst können wir dir auch nicht wirklich weiter helfen, da wir den Code nicht kennen. Das sich das Problem nicht reproduzieren lässt, macht es sicher auch nicht einfacher.

    Du könntest als Abhilfe versuchen einen Fehler in der Methode möglichst Detailliert abzufangen und zu protokollieren. Das ist bei 600 Zeilen natürlich etwas Aufwand, aber so kann man den Fehler noch am ehesten eingrenzen. Was die Fehlermeldung schon ausdrückte ist irgend etwas null bzw. Nothing - also nicht zugewiesen. Einen einfachen Aufruf eines Konstruktors wirst du wahrscheinlich nicht vergessen haben, eher geben Methoden wie FirstOrDefault null zurück und blockieren damit die weitere Ausführung des Codes.

    Was auch geht, aber deutlich schwieriger ist, wäre einen Debugger anzufügen wärend das Programm gerade abgestürzt ist. So könntest du die Fehlerquelle auch identifizieren.
    (Problem müsste reproduzierbar sein oder ein Kunde das Remote-Debuggen zulassen)
    Die exakte Protokollierung wäre daher vielleicht doch der einfachere Weg.

    PS: Um Bilder und Links posten zu können musst du auf Verify Your Account antworten, Link in meiner Signatur.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Donnerstag, 8. Januar 2015 16:11
    Moderator
  • Was auch eine gute Idee ist, um zu verhindern, dass Fehler auftretten und man dann suchen bis zum Umfallen kann, ist die Verwendung von AppDomain.UnhandledException

    Damit kannst du sicherstellen, dass im Falle eines Fehlers du an alle wichtigen Informationen kommst.

    Dies ist ein Event, muss also am besten schon in der App-Klasse (App.cs bei WPF; Program.cs bei WinForms) oder anderswo direkt nach dem Start der Anwendung zugeordnet werden.

    Wenn dann die Zielmethode im Falle eines Fehlers aufgerufen wird, bekommst du den Fehler weitergereicht und kannst diesen dann in einer Log-Datei (z.B. im Order %Temp%) speichern. Eine solche Datei wäre z.B. wie folgt:

    • %temp%\MainApp_x.log

    (Wobei x eine Zahl ist, z.B. das Datum des erstellen des Protokolles. (Siehe DateTime)

    Dann könntest du den Benutzer einfach bitten, den Order %temp% im explorer zu öffnen, und dir die Datei zu schicken.

    PS: Nachdem du solch einen Fehler gefangen hast, solltest du die Anwendung beenden, da der zustand nicht mehr konsistent ist!


    © 2015 Thomas Roskop

    Donnerstag, 8. Januar 2015 16:44
  • was auch eine möglichkeit wäre geeignete try catch pfade einzufügen.

    da muß der kunde halt mitmachen. :)

    try
    {
        sTryCatch = "Markername ....";
    ///// getesteter code ablaufen lassen ...
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString() + Environment.NewLine + sTryCatch);
    }
    dann kann dir der kunde, wenn er bereit ist mitzumachen, leichter eine rückmeldung geben.


    Freitag, 9. Januar 2015 08:34

Alle Antworten

  • Ich würde sagen bei:

    LMVerwaltung.FrmLMBeleg.positionSpeichern()

    greifst Du auf ein Objekt zu, welches nicht vorhanden ist..

    Donnerstag, 8. Januar 2015 08:17
  • Hi,

    naja, Du solltest in der Methode LMVerwaltung.FrmLMBeleg.positionSpeichern() schauen, dass kein benutztes Objekt null (Nothing in VB) ist. Also vielleicht mal mittels line für line steps alle variablen überprüfen, und schauen was da eventuall null sein kann, oder einfach mal per try catch den Fehler abfangen und in eine log datei schreiben lassen (oder sontswie ausgeben), um den Fehler mit diesen Informationen dann zu beheben...

    Viele Grüße,

      Thorsten

    Donnerstag, 8. Januar 2015 08:20
  • Hallo Dario,

    "positionSpeichern" kling nach Liste. Vielleicht ist die Instanz (noch) nicht vorhanden...

    Es würde helfen, wenn du Code bereit stellst.

    MfG

    Dirk

    Donnerstag, 8. Januar 2015 15:07
  • Die Methode positionSpeichern() ist etwas über 600 Zeilen lang, da je nach genauem Vorgang Unterschiedliche Daten aggregiert werden müssen, und innerhalb der Methode werden weitere Methoden zur Validierung, Vorgangsprüfung, anstoßen von Workflows und ausführen von Verbuchungen aufgerufen.

    Leider kann ich den Fehler nicht durch die Debuggingfunktionen in VS weiter eingrenzen, da er sich nicht reproduzieren lässt. Der User der uns den Fehler zuerst gemeldet hat, hatte uns einen Screenshot mit den eingetragenen Daten geschickt, und selbst bei EIngabe der exakt gleichen Daten konnten wir den Fehler nicht nachvollziehen.

    (musste leider das Bild entfernen, da kommt immer eine Meldung, das ich keine Bilder hochladen kann, bis das Konto von Microsoft "geprüft werden kann", was auch immer das heißt...)

    Donnerstag, 8. Januar 2015 15:54
  • Hallo,
    Methoden, die 600 Zeilen lang sind, sind eine schlechte Wahl. Versuche diese in mehr Methoden aufzugliedern, damit eben Dinge wie das Debuggen leichter werden.

    Sonst können wir dir auch nicht wirklich weiter helfen, da wir den Code nicht kennen. Das sich das Problem nicht reproduzieren lässt, macht es sicher auch nicht einfacher.

    Du könntest als Abhilfe versuchen einen Fehler in der Methode möglichst Detailliert abzufangen und zu protokollieren. Das ist bei 600 Zeilen natürlich etwas Aufwand, aber so kann man den Fehler noch am ehesten eingrenzen. Was die Fehlermeldung schon ausdrückte ist irgend etwas null bzw. Nothing - also nicht zugewiesen. Einen einfachen Aufruf eines Konstruktors wirst du wahrscheinlich nicht vergessen haben, eher geben Methoden wie FirstOrDefault null zurück und blockieren damit die weitere Ausführung des Codes.

    Was auch geht, aber deutlich schwieriger ist, wäre einen Debugger anzufügen wärend das Programm gerade abgestürzt ist. So könntest du die Fehlerquelle auch identifizieren.
    (Problem müsste reproduzierbar sein oder ein Kunde das Remote-Debuggen zulassen)
    Die exakte Protokollierung wäre daher vielleicht doch der einfachere Weg.

    PS: Um Bilder und Links posten zu können musst du auf Verify Your Account antworten, Link in meiner Signatur.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Donnerstag, 8. Januar 2015 16:11
    Moderator
  • Hallo Dario,...muss mich da Koopakiller anschließen. 600 Zeilen in einer Methode sind definitiv zu viel. Schau dir mal SOLID an. Sind denn asynchrone Aufrufe im Spiel oder Linq wie Koopakiller erwähnt hat. Wie wird sichergestellt, das die Workflows instanziiert sind (Stichwort Factories) und so weiter.
    Donnerstag, 8. Januar 2015 16:31
  • Was auch eine gute Idee ist, um zu verhindern, dass Fehler auftretten und man dann suchen bis zum Umfallen kann, ist die Verwendung von AppDomain.UnhandledException

    Damit kannst du sicherstellen, dass im Falle eines Fehlers du an alle wichtigen Informationen kommst.

    Dies ist ein Event, muss also am besten schon in der App-Klasse (App.cs bei WPF; Program.cs bei WinForms) oder anderswo direkt nach dem Start der Anwendung zugeordnet werden.

    Wenn dann die Zielmethode im Falle eines Fehlers aufgerufen wird, bekommst du den Fehler weitergereicht und kannst diesen dann in einer Log-Datei (z.B. im Order %Temp%) speichern. Eine solche Datei wäre z.B. wie folgt:

    • %temp%\MainApp_x.log

    (Wobei x eine Zahl ist, z.B. das Datum des erstellen des Protokolles. (Siehe DateTime)

    Dann könntest du den Benutzer einfach bitten, den Order %temp% im explorer zu öffnen, und dir die Datei zu schicken.

    PS: Nachdem du solch einen Fehler gefangen hast, solltest du die Anwendung beenden, da der zustand nicht mehr konsistent ist!


    © 2015 Thomas Roskop

    Donnerstag, 8. Januar 2015 16:44
  • was auch eine möglichkeit wäre geeignete try catch pfade einzufügen.

    da muß der kunde halt mitmachen. :)

    try
    {
        sTryCatch = "Markername ....";
    ///// getesteter code ablaufen lassen ...
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString() + Environment.NewLine + sTryCatch);
    }
    dann kann dir der kunde, wenn er bereit ist mitzumachen, leichter eine rückmeldung geben.


    Freitag, 9. Januar 2015 08:34
  • @ sleepy007,

    prinzipiell ist dies eine Mögliche Lösung (wobei dir ein kleiner Tippfehler eingeschlichen ist. sTryCatch wurde nirgend definiert. Da es aber sowohl im TRY-, als auch im CATCH-Block verwendet wird, würde ich es drüberliegend erstellen:

    string sTryCatch;
    
    try {
     //Der Rest wie oben!!!

    )

    Im Übrigen ist dies aber eine weniger geeignete Lösung. Denn:

      • Die Ausgabe solch einer Datenmenge sollte aus Sicherheitsgründen niemals an den Benutzer erfolgen! (Zugegeben, dass gilt vor allem bei Serveranwendungen...)
      • Es könnte den Benutzer irritieren. Denn dieser weiß nicht, dass es für den Entwickler nützlich ist und sieht erstmal nur einen großen Haufen, für ihn kryptischen, Text. Eben wegen solcher Verwirrungen zeigen moderne Programme nur noch weniger Fehlermeldungen an. Beispiel: Der BlueScreen of Death von Windows 8 sieht "angenehmer" als der von Windows XP aus, weil es weniger Text enthäkt und nicht so fatal wirkt.

    Ich würde dir tatsächlich eher zu einer Protokolldateibasierten Lösung raten (wenn es auch größer sein darf, dann verwende gleich die Ereignisanzeige von Windows (Event Viewer)!). Aber für ein "normales" Programm dürfte eine einfache Protokolldatei reichen.

    //Ganz triviale Möglichkeit der Protokollierung try { //... Dein fehlerhafter (!?) Code } catch (Exception ex) { string fn = Environment.ExpandEnvironmentVariables("%temp%\MyAppLog.log");

    //Siehe auch http://msdn.microsoft.com/de-de/library/system.environment.expandenvironmentvariables%28v=vs.110%29.aspx //Ganz einfaches Schreiben, ohen Stream oder ähnlichem File.WriteAllText(fn, ex.ToString()); //Schreibt die Datei in die Protokolldatei.

    //Siehe dazu auch http://msdn.microsoft.com/de-de/library/ms143375%28v=vs.110%29.aspx //Den Benutzer informieren, dass es die Datei gibt. Ein netter Text :) string message = "Uups, Leider ist ein Fehler in der Anwendung eingetreten.\nDie Anwendung muss beendet werden.\n\nGenauere Fehlerinformatione sind in folgender Datei gesammelt worden: {0}"; string fM = string.Format(message, fn); MessageBox.Show(fM, "Fehler!"); //Fehlermeldung anzeigen anzeigen }


    Mit solch einer "netten" Fehlermeldung wird der Benutzer nicht erstmal in Rage versetzt, denn Computer-Benutzer scheinen, nach dem was ich schon alles bei anderen gesehen habe, sehr schnell irritiert zu sein von seltsamen Fehlern.


    © 2015 Thomas Roskop


    Samstag, 10. Januar 2015 15:15