Allgemeine Exception Routine

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

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von EaranMaleasi.

    Allgemeine Exception Routine

    Hi,

    Ich möchte bei einem umfangreichen Directory Search die auftretenden Fehler in ein Log schreiben. Der Exception Code soll darin natürlich aufgeführt werden.

    Das hab ich wie folgt versucht:

    VB.NET-Quellcode

    1. Catch ex As Exception
    2. errorCount += 1
    3. Dim strType As String
    4. Select Case ex.GetType
    5. 'Case UnauthorizedAccessException : strType = "UA"
    6. 'Case IOException : strType = "IO"
    7. Case Else : strType = "NN"
    8. End Select
    9. errorList.Add(DateTime.Now.ToString("HH:mm:ss") & ";" & strType & ";" & chkObject)
    10. ...


    Die beiden auskommentierten Anweisungen funktionieren natürlich nicht.

    ex.GetType is vom Typ Type

    Wo krieg ich denn jetzt die zugehörige Konstante her, die etwa UnauthorizedException entspricht ?

    LG
    Peter
    @Peter329 Die Exceptions musst Du einzeln abfangen:

    VB.NET-Quellcode

    1. Try
    2. ' was tun
    3. Catch ex As System.IO.FileNotFoundException
    4. MessageBox.Show("a")
    5. Catch ex As System.IO.DriveNotFoundException
    6. MessageBox.Show("b")
    7. Catch ex As Exception
    8. MessageBox.Show("c")
    9. End Try
    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!
    Genauso habe ich das zunächst auch gemacht ... und dann halt in den einzelnen Zweigen die gleiche Routine zum Bearbeiten des Fehlers aufgerufen.

    Das erschien mir aber einfach zu umständlich! Denn in ex.Type kriegt man den Exception Type zurückgeliefert. Im Debugger kann ich den problemlos mit .tostring anzeigen. Und damit funktioniert dann auch das folgende Coding:

    VB.NET-Quellcode

    1. Select Case ex.GetType.ToString
    2. Case "System.UnauthorizedAccessException" : strType = "UA"


    Aber das kann ja wohl nicht die ultima ratio der schönen neuen objektorientierten Welt sein, dass ich das Dinges in einen String umwandeln muss, um es abzufragen ...
    Wenn es nur ums Mitschreiben der Exceptions geht, kannst du auch getrost Exception catchen und nichts anderes.
    Wichtig ist sowieso
    1. die Message der Exception, in der auch nochmal angegeben ist, um welchen Exception-Typ es geht (z.B. "Eine Exception vom Typ System.NullReferenceException ist aufgetreten")
    2. der StackTrace der dir sagt wo der Fehler aufgetreten ist.
    Die Kombination aus beiden bekommst du aus der .ToString() Methode einer Exception.
    Und nicht vergessen nachzusehen, ob es noch eine InnerException gibt. Bei der dann natürlich das Selbe mitloggen.

    Möchtest du natürlich auf verschiedene Exceptions verschieden reagieren kommste um mehrere Catch-Blöcke nicht drum rum.
    Ok ... dann muss ich also schon mit .tostring umwandeln und dann abfragen.

    So sieht das jetzt bei mir aus:

    VB.NET-Quellcode

    1. Catch ex As Exception
    2. errorCount += 1
    3. Dim strType As String = ex.GetType.ToString '***TEST
    4. Debug.Print(strType) '***TEST
    5. Select Case ex.GetType.ToString
    6. Case "System.UnauthorizedAccessException" : strType = "UA"
    7. Case "System.IO.IOException" : strType = "IO"
    8. Case Else : strType = "NN" 'Unexpected error
    9. End Select
    10. errorList.Add(DateTime.Now.ToString("HH:mm:ss") & ";" & strType & ";" & chkObject)
    11. ...


    So funktioniert das jetzt in meinem Sinne. Danke an die Ratgeber !

    LG
    Peter
    @Peter329 Das geht ohne ToString, gugst Du hier.

    VB.NET-Quellcode

    1. Try
    2. ' was tun
    3. Catch ex As Exception
    4. Dim t As Type = ex.GetType()
    5. If t.Equals(GetType(System.IO.DriveNotFoundException)) Then
    6. MessageBox.Show("a")
    7. ElseIf t.Equals(GetType(System.IO.FileNotFoundException)) Then
    8. MessageBox.Show("b")
    9. Else
    10. MessageBox.Show("c")
    11. End If
    12. End Try
    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!
    Ich hab doch gewusst, dass RFG dafür eine Lösung kennt ! :) Das mit dem .ToString kann man doch so nicht stehen lassen !

    Danke ... jetzt sieht das alles doch sehr viel ordentlicher aus!

    LG
    Peter
    @Peter329 Ich hab auch nur nach VB.NET GetType gesucht und mir die ersten beiden oder derei Vorschläge angesehen. Allerdings wusste ich, dass es da was gibt.
    Das solltest Du auch können. ;)
    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!
    Wie earanmaleasi schreibt kannst du auch (oder solltest sogar) in Betracht ziehen, einen "CatchAll" durchzuführen.
    Dabei (wie er ebenfalls sagt) kannst du einfach Exception.ToString() loggen - die ToString()-Implementation von Exceptions ist überaus ausführlich, und teilt u.a. auch den genauen Typ der Exception mit.

    Auf jeden Fall ist .GetType() hier eher nicht Mittel der Wahl, denn nach Typen unterscheidet der Catch-Abschnitt ja schon von sich aus.

    VB.NET-Quellcode

    1. Try
    2. ' was tun
    3. Catch ex As UnauthorizedAccessException
    4. MessageBox.Show(ex.ToString)
    5. Catch ex As DirectoryNotFoundException
    6. MessageBox.Show(ex.ToString)
    7. Catch ex As FileNotFoundException
    8. MessageBox.Show(ex.ToString)
    9. End Try
    Das hier fängt also dreierleich Exceptions ab, bei allem anderen gibts einen Programm-Abbruch (was evtl. vorzuziehen ist).

    Catch all geht einfach so:

    VB.NET-Quellcode

    1. Try
    2. ' was tun
    3. Catch ex As Exception
    4. MessageBox.Show(ex.ToString)
    5. End Try
    Was bisserl heikel ist, weil auch die dümmsten Fehler durchgelassen werden, statt zu crashen.

    Und probiermal mit Exception.ToString herum - wenn ich mich recht erinnere, gibt das sogar die InnerException gleich mit aus - wie gesagt: .ToString() ist bei Exceptions echt "verbose".

    Du kannst auch folgendes überlegen:

    VB.NET-Quellcode

    1. Try
    2. ' was tun
    3. Catch ex As UnauthorizedAccessException
    4. MessageBox.Show(ex.ToString)
    5. Catch ex As IOException
    6. MessageBox.Show(ex.ToString)
    7. End Try
    Mit IOException fängst du die gemeinsame Basisklasse von FileNotFound, DirectoryNotFound, und evtl. noch paar annere, an die man nicht gleich denkt (DriveNotFound?).

    ErfinderDesRades schrieb:

    wenn ich mich recht erinnere, gibt das sogar die InnerException gleich mit aus
    Tut es:
    stackoverflow.com/questions/59…y-the-full-innerexception

    Man sollte catchen was man behandeln kann, und alles was man nicht kann aufschreiben und weiterwerfen. Dann kann man vom User einfach das Logfile verlangen und er muss sich nicht den (teils) meterlangen Stacktrace ansehen. Jeder ist glücklich, da die Anwendung nicht in einem unbekannten Zustand weiterarbeitet, sondern die Integrität der Daten bewahrt mit ihrem Crash. Bis der Fix kommt kann der User die "Funktion" dann umgehen. Nichts ist schlimmer als Datenverlust aufgrund eines ungewollten Verhaltens der Anwendung.
    Allgemeine Exception Routine In deinem kommentierten Teil fehlt Is.

    Also:

    VB.NET-Quellcode

    1. Select Case ex.GetType
    2. Case Is UnauthorizedAccessException : strType = "UA"
    3. Case Is IOException : strType = "IO"
    4. Case Else : strType = "NN"
    5. End Select


    Grüße
    Väinämö

    Vainamo V schrieb:

    Select Case ex.GetType
    Case Is UnauthorizedAccessException : strType = "UA"


    Das klingt zwar gut ... aber ich erhalte damit den Compiler Fehler:

    Fehler BC30239 Relationaler Operator erwartet.

    Schade.

    Zur Diskussion über das Abfangen von Fehlern. Ich durchsuche einen frei wählbaren, kompletten Verzeichnisbaum. Der Dialog stellt sicher, dass nur ein gültiger Basis Pfad ausgewählt werden kann. Die Suche wird nach verschiedenen Kriterien eingeschränkt (Alter der Datei, Größe der Datei, Namen der Datei, Inhalt der Datei).

    Wenn man etwa das komplette C-Laufwerk durchsucht, dann sind bestimmte Fehler zu erwarten: Unauthorized Access (etwa für C:\Users), IOException (etwa für pagefile.sys) etc.

    Es macht doch jetzt überhaupt keinen Sinn die Suche bei einem Fehler abzubrechen. Ganz im Gegenteil ... alle Dateien die bereits gefunden wurden und noch gefunden werden, sind doch absolut von Interesse. Ich muss halt wissen, welche Dateien übersprungen wurden und warum. Da ggf. tausende Fehler auftreten können, macht es Sinn so etwas in einen Log File zu schreiben, den ich hinterher bedarfsweise anzeigen und auswerten kann. Also ich finde, das ist schon eine sinnvolle Anwendungen für Try-Catch ohne Abbruch.

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

    Ich habe nie behauptet, dass Try-Catch ohne Abbruch böse wäre:

    EaranMaleasi schrieb:

    Man sollte catchen was man behandeln kann, und alles was man nicht kann aufschreiben und weiterwerfen.
    Sachen wie Unauthorized Access usw. kann durchaus behandelt werden, und wenn dies lediglich bedeutet, den Fehler zu schlucken, weil man keine Admin-Rechte hat. Muss man halt den User drauf hinweisen, dass der Applikation die Rechte fehlen um entsprechende Dateien zu öffnen.