Try-Catch un ein paar Rätsel

Hallo alsseits,

ich versuche gerade, eine Exception auszulösen und mit catch abzufangen. Das Besondere daran: der Trigger soll in einer Subroutine sitzen, die eine Abbrechen/Wiederholen/Ignorieren Funktion implementiert. Wiederholen und Ignorieren sind kein Problem, das kann man wie im Beispiel locker mit einer Schleife machen. Abbrechen soll natürlich nicht das ganze Programm abbrechen, sondern in der Routine, die den Verzeichnislöscher ursprünglich aufgerufen hat, noch schnell ein paar Aufräumaktionen durchziehen, und dann zum Hauptprogramm zurückkehren.

Hier mein Beispielcode (Verzeichnis löschen) um das Problem zu erklären:

Module Module1

Dim exAbort As Exception 'Rätsel 1

Function ErrorHandler(ByVal strMessage)

ErrorHandler = MsgBox(strMessage, vbAbortRetryIgnore)
If ErrorHandler = vbAbort Then
Throw exAbort 'Abbruch bei „Abbrechen“ Button
End If
End Function

Sub RemoveDirectory(ByVal strPath As String)

’ Remove a directory

Dim iControl
Do ’ Schleife für „Wiederholen“ und „Ignorieren“ Buttons
iControl = vbIgnore
Try
System.IO.Directory.Delete(strPath)
Catch ex As Exception
iControl = ErrorHandler("Cannot remove directory: " &
strPath)
End Try
Loop Until (iControl = vbIgnore)
End Sub

Sub Main()

Try
RemoveDirectory(„c:\temp\xxx\yyy\zzz“)
MsgBox(„Directory removed (or error ignored)“)
Catch ex As Exception
MsgBox(„Directory remove: Abort Pressed!“)
Finally
MsgBox(„Cleanup!“)
End Try
End Sub

End Module

Die gute Nachricht: Das Programm funktioniert. Wenn das Verzeichnis nicht exitsiert, und der Benutezr „Abbrechen“ wählt, macht das Programm im Finally Block der Main() Routine weiter. Ich weiß nur nicht, warum.

Erstens ist die Deklaration von exAbort völlig widersinnig. Ich muss sie aber so schreiben, alles Andere geht nicht durch den Compiler.

Zwei Varianten, die Sinn machen würden:

lokale Deklaration

Dim exAbort as Exception

innerhalb von ErrorHandler. Unter der Annahme, dass jeder Throw einer eine Exception den nächstgelegenen Try…Catch triggert. Pustekuchen, Eine Exception lässt sich lokal nicht deklarieren. Gut, meinetwegen, die globale Deklaration stört mich nicht, aber dann möchte ich in der Main () Routine natürlich

catch exAbort

schreiben. Klappt aber auch nicht.

Zur Frage, wie Exceptions in Subroutinen ausgelöst werden können habe ich leider keinerlei brauchbare Doku gefunden. Was ich durch Probieren herausgefunden habe triggert Throw innerhalb eines Try Blocks die Exception genau dieses Blocks (muss sich natürlich in der selben Routine befinden), und innerhalb des Catch Blocks aufgerufen den Catch Block der nächstübergeordneten Routine die einen Try…Catch Block hat.

Eine Routine ohne eigenen Try…Catch Block scheint im Catch Block der nächstübergeordneten Routine zu enden. Ich vermute, dass mein Code deshalb funktioniert. Bleibt allerdings die hässliche Deklaration. oder ich habe mir da was falsch zusammengereimt.

Kann jemand ein wenig mehr Licht ins Dunkel bringen? Umgebung ist Visual Studio 2005 / Visual Basic Console Application.

Danke,

…Armin

Hallo Armin,

so ganz verstanden habe ich nicht, was Du erreichen willst, aber ein paar Tips:

Du kannst an jeder Stelle eines Programms eine Exception auslösen:

Throw New Exception("Fehlernachricht")

Damit wird die Deklaration überflüssig.
Wenn eine Exception nicht lokal abgefangen wird, wird sie „nach oben“, also an die aufrufenden Routinen weitergereicht. Falls Du in der Aufrufhierarchie nirgends einen Try-Catch-Block hast, erzeugt .net eine entsprechende Fehlermeldung, die in einer Applikation aber sehr unschön aussieht und außerdem das Programm beendet.

In Deinem Beispiel erachte ich die Function ErrorHandler als überflüssig, da Du die MsgBox auch im Catch-Block der Sub RemoveDirectory hättest anzeigen können.

Grundsätzlich noch: Ich würde auf jeden Fall die Optionen „Explicit“ und „Strict“ auf „On“ setzen. Das hilft Fehler zu vermeiden.

Gruß
Thomas

Hallo Thomas,

Dein Ansatz löst das Problem. Ich hatte einfach eine andere Vorstellung von Exceptions, die Doku und die Deklaration verleiten ein wenig dazu eine Exception als eine Art Variable zu betrachten. Es ist tatsächlich so wie Du sagst: der Name der Exception („bla“ in „Catch bla as exception“) ist völlig egal, und eine Exception in einer Subroutine triggert immer den Catch Block der aufrufenden Routine, völlig wurscht wie die Exception in der Subroutine genannt wird.

Danke für den Denkanstoß,

Armin.