Fehlerbehandlung: Gibt es Verbesserungsmöglichkeiten?

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 50 Antworten in diesem Thema. Der letzte Beitrag () ist von VaporiZed.

    Fehlerbehandlung: Gibt es Verbesserungsmöglichkeiten?

    Eine Frage zur Fehlerbehandlung mit Try Catch usw..
    Habe mir ein DataTable mit BindingSource etc aufgebaut und lasse die Textboxen für Eingaben dahingehend prüfen, das keine NULL-Werte erlaubt sind.
    Der nachfolgende Code funktioniert prima. Er schreibt mir, wenn alles OK ist mein XML-File oder wenn ein Fehler auftritt mein Logfile.

    Jetzt meine Frage: Ist das so "erlaubt" könnte man das noch "verbesssern" Ohne das ganze komplett umzuschreiben?
    Der ganze Code liegt in dem Form!

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Dim MyxmlFile As String = "Settings.xml" 'Application.StartupPath &
    2. Dim MyLogFile As String = "Logfile.txt" 'Application.StartupPath &
    3. Dim HDDS As DriveInfo() = DriveInfo.GetDrives()
    4. Dim savesuccess As Boolean = False
    5. #Region "Speichern/Fehlerbehandlung"
    6. Private Sub Btn_save_Click(sender As Object, e As EventArgs) Handles Btn_save.Click
    7. SaveData()
    8. If savesuccess Then
    9. Lbl_error.Visible = True
    10. Lbl_error.Text = "Daten wurden gespeichert."
    11. Else
    12. If MessageBox.Show("Ein Fehler ist passiert." & Environment.NewLine & "Die LogDatei öffnen?", "Hinweis", MessageBoxButtons.YesNo, MessageBoxIcon.Information) = DialogResult.Yes Then
    13. System.Diagnostics.Process.Start("Logfile.txt")
    14. End If
    15. End If
    16. End Sub
    17. Private Sub SaveData()
    18. Try
    19. Me.Validate()
    20. Me.DTsettingsBS.EndEdit()
    21. Appsettings.WriteXml(MyxmlFile)
    22. savesuccess = True
    23. Catch ex As Exception
    24. ExceptionToFile(ex.Message)
    25. End Try
    26. End Sub
    27. Public Sub ExceptionToFile(ByVal ExceptionMessage As String)
    28. File.AppendAllText(MyLogFile, ExceptionMessage)
    29. File.AppendAllText(MyLogFile, Environment.NewLine)
    30. End Sub
    31. #End Region

    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Habe mir ein DataTable mit BindingSource etc aufgebaut und lasse die Textboxen für Eingaben dahingehend prüfen
    Du könntest ev. über die Binding-Klasse deine Eingabe über das Parse-Event prüfen und damit eine mögliche Exception vorbeugen...
    Du musst aber vorher mit dem Designer das vorhandene Binding von der Textbox lösen!
    Natürlich wird deine Textbox über die Bindingsource zu Fuß per Benutzer-Code angelegt (siehe die Methode BindControl im Beispiel)!
    Und dann kannst du das Parse-Event nützen, um deine Eingaben auf Korrektheit prüfen...
    Schaue dir dazu eventuell das Format-Event an - damit kannst du deine Eingaben formatieren...
    @Amelie Im Debug-Code mit Compilerschalter machst Du ein Debugger.Break(), damit Du Exceptions, die durch Programmierfehler entstehen, sofort untersuchen kannst:

    VB.NET-Quellcode

    1. #If DEBUG Then
    2. If Debugger.IsAttached Then
    3. Debugger.Break()
    4. End If
    5. #End If
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    Das mit dem Compilerschalter verstehe ich noch nicht.
    @VB1963
    Habe meinen Code nochmal überarbeitet und die Textboxen gegen Combos getauscht. Eingestellt als "DropDownList" und wieder an die BindingSouce gebunden.
    Prüfen tue ich diese so: (für mich z.Zt. am einfachsten)

    VB.NET-Quellcode

    1. Private Sub EingabenPrpüfen()
    2. If CmbBox_workhdd.SelectedIndex = -1 OrElse CmbBox_backuphdd.SelectedIndex = -1 OrElse CmbBox_quellhdd.SelectedIndex = -1 OrElse CmbBox_temphdd.SelectedIndex = -1 Then
    3. combosemty = False
    4. Exit Sub
    5. Else
    6. combosemty = True
    7. End If
    8. End Sub
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Die ganze Eingabeprüfung kannst du auf eine Zeile reduzieren

    VB.NET-Quellcode

    1. ​combosempty = CmbBox_workhdd.SelectedIndex <> -1 AndAlso CmbBox_backuphdd.SelectedIndex <> -1 AndAlso CmbBox_quellhdd.SelectedIndex <> -1 AndAlso CmbBox_temphdd.SelectedIndex <> -1
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

    Amelie schrieb:

    Das mit dem Compilerschalter verstehe ich noch nicht.

    Also du kannst in den Projekteigenschaften solche Sachen festlegen, für jede Buildeinstellung.
    Im Code kannste dann je nach Buildkonfiguration unterschiedliche Sachen anstellen.

    Geh mal in die Projekteigenschafte, reiter Kompileren, erweiterte Kompilierungsoptionen. Siehe Screenshot, oben siehst du die konfiguration(Debug/Release) wie auch Platform, jenachdem was du da einstellst, bevor du auf erweiterte Kompilieroptonen klickst, gilt das was du dann einstellst für diese Konfiguration. So kannste dir für jede Kombination(z.B. Debug + x64, oder release + x86) Werte anlegen, hast du eine weitere konfiguration angelegt zusätzlich zu Debug, kannste auch dafür sowas festlegen, beim kompilieren sieht der Kompiler was für die aktuelle Buildeinstellung festgelegt ist und du kannst im Code "switchen" so wird entweder der eine oder ein anderer Code an dieser Stelle kompilert. Legst du z.B. neben Debug und Relaese eine weitere Option an, z.B. mit dem Name ExtendedDebug und schreibst für diese Einstellung dann nur ExtendedDebug in die TB in den erweiterten kompiliereinstellungen, ist das definiert, auch wenn du keinen Wert zuweist, jenach buildeinstellung kannste auch verschiedene werte für4 die konstante festlegen und abfragen.

    Ich habe jetzt mal neben Debug/Release eine weitere Konfiguration angelegt und ExtendedDebug genannt. Für diese Buildeinstellung habe ich eine Konstante angelegt heist auch "ExtendedDebug "(kannste aber nnen wie du willst), ohne einen Wert zuweisen. Im Code kann ich dann so unterschiedlichen Code kompileren. Dabei habe ich bei dieser konfiguration auch die Checkbox bei DEBUG konstante definieren unchekced.

    Wie du auf dem 2. Bild sehen kannst, ist der Code im DEBUG bereich ausgegraut, dann bekommt x den Wert 20.
    Schalte ich nun die Konfiguration wieder auf Debug um, würde x den Wert 10 haben, bei release würde es bei 0 bleiben.

    Nicht immer stelle ich alle Funtionen eines Programms im releasebuild zur Verfügung, so kannste dann schnell und einfach festlegen, ob die normale oder erweiterte Version kompiliert werden soll. Oder wenn ein Client probleme mit dem Programm hat, kannste dem so einen releaseBuild geben der alles loggt, dir das log dann geben lassen um Fehler zu beseitigen.
    Bilder
    • Unbenannt.jpg

      95,8 kB, 1.272×771, 53 mal angesehen
    • Unbenannt1.jpg

      27,48 kB, 989×378, 61 mal angesehen

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „Takafusa“ ()

    @RodFromGermany Wozu

    VB.NET-Quellcode

    1. #If DEBUG Then
    2. #End If


    Gibt es irgendeinen Grund eine Debug-Version anzuhalten, wenn kein Debugger angehängt ist?

    VB.NET-Quellcode

    1. If Debugger.IsAttached Then
    2. End If


    Reicht doch völlig oder. Unter Umständen ist das sogar hilfreich, für den Fall, dass man mal eine Release-Version debuggen muss. Kommt ja auch mal vor, wenn auch selten.


    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.
    @Takafusa
    Meine Frage war nicht, ob das möglich ist, denn dessen bin ich mir sehr wohl bewusst. Meine Frage war, in welchem Szenario dies sinnvoll sein soll / jemals benötigt werden sollte.

    In Anspielung darauf das #If DEBUG Then realistisch betrachte eher selten irgendeinen Nutzen erfüllt und ganz sicher nicht in dem oben beschrieben Szenario. An dieser Stelle ist das meiner Meinung nach einfach redundanter unnützer Code, weil mir persönlich kein Szenario einfällt in dem man einen break macht ohne angehängten Debugger.


    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Yanbel“ ()

    Yanbel schrieb:

    An dieser Stelle ist das meiner Meinung nach einfach redundanter unnützer Code, weil mir persönlich kein Szenario einfällt in dem man einen break macht ohne angehängten Debugger.
    Pack mal Deinen und meinen Code in den IlSpy.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany Kann ich leider gerade nicht, ich bin noch unterwegs. Ich vermute aber mal, dass du darauf hinaus willst, dass dein Code im Release nicht kompiliert wird und meiner schon.

    Wie bereits in Post #7 geschrieben und in Post #9 wiederholt, ist das hier aber gar nicht die Frage, sondern vielmehr ob das generell oder speziell für den Anwendungsfall des TE sinnvoll ist, weil man ja ggf. auch Release-Versionen nachträglich debuggen muss, wo Breaks im zentralen Errorhandling unter Umständen durchaus hilfreich sein können. Ausgeführt wird der Code doch ohnehin nur, wenn ein Debugger angehängt wird. Und mit Performance braucht mir hier auch keiner kommen. Die Abfrage eines oder einer Million bool-Variablen ist nicht sonderlich Performance-intensiv hab ich gehört, stört also auch nicht im Release. Schön je nachdem wieviel Code man in diese Tags reinschreibt kann das Kompilieren sich unter Umständen leicht verzögern, aber seien wir mal ehrlich, wenn das tatsächlich der Fall sein sollte, dann hat der Entwickler grundlegend was falsch gemacht. Also wo ist der Nutzen?

    Ich frage an dieser Stelle bewusst provokant, weil wir auf der Arbeit gerade im gesamten Programmcode #If DEBUG Then rausgeschmissen bzw in wenigen Fällen durch if (Debugger.IsAttached)) ersetzt haben. Mich würde tatsächlich mal interessieren, ob irgendjemandem hier ein guter Grund einfällt, dieses Code-Tag jemals irgendwo zu verwenden.


    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.

    Yanbel schrieb:

    im gesamten Programmcode #If DEBUG Then rausgeschmissen
    Wir nicht.
    Ich arbeite sehr gern damit, auch ist bei uns in vielen Datenklassen die ToString()-Überladung nur im Debug vorhanden.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Wir sind irgendwann dazu übergegangen, dass sich unsere Entwicklungsumgebung genau so verhalten muss, wie die Live-Umgebung des Kunden. Ich benutze DEBUG-Schalter generell nicht, meine Kollegen noch ab und an für Fälle wie SELECT * FROM Customer-> SELECT TOP 1000 * FROM Customer, um Ladevorgänge zu verkürzen, etc. Ich habe noch nie einen Nutzen darin gesehen. Dann lieber vernünftigt Debuggen. Der einzige Punkt wo ein Schalter wirklich wichtig und sinnvoll ist, ist bei Außenkommunikation. Mailversand und Datentransfer in externe Systeme sollten in Testumgebungen unterbunden werden. Das war der einzige Punkt den wir unangetastet gelassen haben.


    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.
    Wenn ich einen Rechner ohne Hardware habe, kann ich mit Compilerschalter eine Hardware-Simulation laden, um am Rest des Programms zu arbeiten.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Amelie schrieb:

    Jetzt meine Frage: Ist das so "erlaubt"?
    Naja, bei einem Spiel-Programm ist natürlich alles erlaubt, was kompiliert.
    In der Praxis kommts dann auf den Einzelfall an, ob sowas "erlaubt" ist - meist ist es das nicht.

    Du hast da jetzt etwas gebaut mit einem Speicher-Vorgang, und wenn das Speichern fehlschlägt, erscheint eine Meldung, und das Programm läuft weiter.
    In der Praxis - etwa bei der Eingabe von KundenDaten - wäre so etwas extrem heikel.
    Weil wenn so eine zentrale Funktionalität wie das Abspeichern von KundenDaten nicht funktioniert, dann darf das Programm nicht weiter benutzt werden.
    Es muss geschlossen werden, so unschön das auch sein mag.

    Amelie schrieb:

    Habe meinen Code nochmal überarbeitet und die Textboxen gegen Combos getauscht. Eingestellt als "DropDownList" und wieder an die BindingSouce gebunden.
    Eine ComboBox, die an eine gefüllte BindingSource gekoppelt ist, hat immer eine getroffene Auswahl. Eine Überprüfung auf Nichtauswahl wäre daher überflüssig, da das nie eintreten kann - es sei denn, man fummelt an der BindingSource/Datenquelle rum.
    Meine ClearableComboBox kann sowas, aber die normale ComboBox im Zusammenhang mit einer BindingSource nicht.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @ErfinderDesRades
    ​Es muss geschlossen werden, so unschön das auch sein mag
    Kann man das Prog dann nicht in " schön " bzw dann " kontrolliert " herunterfahren?

    @VaporiZed
    ​hat immer eine getroffene Auswahl.
    Also ich habe nirgends "rumgefummelt" aber die Combos haben nichts ausgewählt wenn ich das Prog starte.

    -----
    Ich habe nun hier im Forum etwas gelesen bzgl MySettings das man die so nicht einfach mit in dem Programmpath ablegen kann.
    Jetzt überlege ich einfach eine XML zu machen, ohne großartig DataTable etc. Da sollen einfach nur max 5 Werte ( 4 Strings und 1 Boolen ) drin abgelegt werden.
    Also baue ich mir eine Klasse mit den Propertys, einer "speichern-funktion" und gut wäre es?
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Kann man das Prog dann nicht in " schön " bzw dann " kontrolliert " herunterfahren?
    Bei einer unerwarteten Exception wird eine sinnvolle Log-Datei geschrieben, eine MessageBox mit einer sinnvollen Ausschrift gezeigt, z.B. soll die Log-Datei an Dich gesendet werden, und das Programm wird beendet.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Bis auf das Beenden vom Prog habe ich das so. Das LogFile wird ja geschrieben.

    VB.NET-Quellcode

    1. Private Sub SaveData()
    2. Try
    3. Me.Validate()
    4. Me.DTsettingsBS.EndEdit()
    5. Appsettings.WriteXml(MyxmlFile)
    6. savesuccess = True
    7. Catch ex As Exception
    8. ExceptionToFile(ex.Message)
    9. End Try
    10. End Sub
    11. Public Sub ExceptionToFile(ByVal ExceptionMessage As String)
    12. File.AppendAllText(MyLogFile, ExceptionMessage)
    13. File.AppendAllText(MyLogFile, Environment.NewLine)
    14. End Sub


    Da bräuchte ich dann ja eigentlich nur noch etwas "einbauen" wie "Application Exit" ??
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Sind alle ComboBoxen an BindingSources gebunden und diese an das typisierte DataSet? Kommen die Daten bei Programmstart ins tDS oder erst später?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.