Was wäre eine Anwendung ohne Fehlerbehandlung Auch wenn wir in den bisherigen Beispielanwendungen meist gar keine Fehlerbehandlung genutzt haben, weil der Code so übersichtlicher ist. Wenn Sie aber eine Anwendung an Kunden weitergeben, sollte diese keine unbehandelten Ausnahmen liefern. Deshalb beschreiben wir im vorliegenden Artikel, wie die Fehlerbehandlung unter VB.NET funktioniert und welche Unterschiede sich zur Fehlerbehandlung unter Access/VBA ergeben.
Beispiele ausprobieren
Wir haben die Beispiele im Tool LINQPad eingegeben und ausprobiert. Das Tool ist in der Basisversion kostenlos und erlaubt das Ausführen von VB.NET-Prozeduren, ohne das Sie immer erst ein Projekt zum Debuggen starten müssen. Den Download des Tools finden Sie unter www.linqpad.net.
Von VBA zu VB.NET
Unter VBA war die Fehlerbehandlung recht einfach: Wir haben mit On Error Resume Next festgelegt, dass die Fehlerbehandlung für die folgenden Zeilen ausgesetzt wird und haben selbst mit Err.Number geprüft, ob ein Fehler aufgetreten ist und entsprechend darauf reagiert. Damit haben wir dann gezielt Fehler behandelt. Oder man hat zu Beginn einer Prozedur mit einer Anweisung wie On Error Goto Fehler festgelegt, dass die Prozedur im Falle eines Fehlers zu einer Marke namens Fehler springen sollte, wo wir dann eine allgemeine Fehlerbehandlung eingebaut haben, die beispielsweise eine E-Mail mit der Fehlermeldung und weiteren Informationen an den Hersteller der Software geschickt hat.
Wenn Sie eine Anwendung von Access nach VB.NET migrieren und dabei möglichst viel Quellcode übernehmen wollen, gibt es allerdings eine gute Nachricht: Die unter VBA verwendeten Befehle für die Fehlerbehandlung funktionieren auch noch unter VB.NET.
Das folgende klassische Beispiel liefert allerdings nicht den Beweis, dass die Fehlerbehandlung wie unter VBA funktioniert. Dafür benötigen Sie allerdings einen Verweis auf den Namespace Microsoft.VisualBasic:
Sub DivisionByZero On Error Resume Next Debug.Print(1 / 0) If Not (Err.Number = 0) Then Debug.Print("Fehler: " + Err.Number + " " + Err.Description) End If End Sub
Das Ergebnis der Division von 1 und 0 wird nämlich einfach wie folgt ausgegeben:
8
Also lösen wir den Fehler mit der entsprechenden .NET-Anweisung aus, nämlich ThrowException:
On Error Resume Next Throw New DivideByZeroException() 'Debug.Print(1 / 0) If Not (Err.Number = 0) Then Debug.Print("Fehler: " & Err.Number & " " & Err.Description) End If
Damit haben wir auch gleich die erste Anweisung der Ausnahmebehandlung unter VB.NET kennengelernt – die Thow-Anweisung dient dazu, Ausnahmen auszulösen. Mehr dazu weiter unten! Übrigens sollten Sie, auch wenn es möglich ist, nicht mehr die von VBA gewohnten Möglichkeiten zur Fehlerbehandlung nutzen.
Fehlerbehandlung unter VB.NET
.NET bietet wesentlich umfassendere Möglichkeiten für die Fehlerbehandlung oder, wie man hier sagt, Ausnahmebehandlung. Die grobe Richtschnur für eine Fehlerbehandlung unter VB.NET ist ein Block ähnlich einer If…Then…Else-Bedingung mit den drei Anweisungen Try, Catch und Finally. Die Mindestanforderung sind die beiden Anweisungen Try, Catch und die End Try-Anweisung:
Try
'auszuführender Code, der eine Ausnahme auslösen könnte
Catch ex As Exception
'Code, der beim Auftreten der Ausnahme ausgeführt werden soll
End Try
Das Pendant zu der Fehlerbehandlung von oben mit der Division durch 0 würde also wie folgt aussehen:
Sub DivisionByZeroVBNET Try Throw New DivideByZeroException() Catch ex As Exception Debug.Print("Fehler: " & ex.Message) End Try End Sub
Der Aufbau ist also prinzipiell gar nicht so viel anders als unter VBA. Der Teil zwischen Catch… und End Try wird nur ausgeführt, wenn eine Ausnahme ausgelöst wird. Ein wichtiger Unterschied: Es gibt unter VB.NET kein Err-Objekt (zumindest nicht, wenn Sie Try…Catch verwenden). Dafür legen Sie in der Catch-Anweisung jedoch ein Objekt des Typs Exception fest, hier mit der Bezeichnung ex. Exception liefert uns wie Err zwar eine Meldung, aber keine Fehlernummer.
Wie sollen wir das nun vernünftig auswerten und je nach Fehler entsprechend reagieren
Ganz einfach: Es gibt für jede Ausnahme eine spezielle Exception. Für diesen Fall ist diese leicht zu finden, denn die Exception wird durch das “Werfen” der Ausnahme DivideByZeroException ausgelöst. Dementsprechend können wir die Catch-Anweisung direkt etwas genauer definieren, sodass diese nur auf DivideByZeroException-Ausnahmen reagiert:
Sub DivisionByZeroVBNET_DivideByZeroException Try Throw New DivideByZeroException() Catch ex As DivideByZeroException Debug.Print("Fehler: " & ex.Message & " ") End Try End Sub
Da Sie wissen, welcher Fehler hier behandelt wird, können Sie die Meldung auch anpassen, ohne auf ex.Message zuzugreifen:
Debug.Print ("Division durch Null.")
Tritt nach der Try-Anweisung eine andere Ausnahme als DivideByZeroException auf, führt dies allerdings zu einer unbehandelten Ausnahme – zum Beispiel wenn Sie mit folgender Anweisung einen Dateifehler auslösen:
Throw New FileNotFoundException
Wir sollten also auch mit der allgemeinen Ausnahme Exception alle möglichen Ausnahmen abfangen. Dazu fügen wir einfach einen weiteren Catch-Zweig zu dem Konstrukt hinzu:
Try Throw New FileNotFoundException Throw New DivideByZeroException() Catch ex As DivideByZeroException Debug.Print("Die Datei konnte nicht gefunden werden.") Catch ex As Exception Debug.Print("Fehler: " & ex.Message) End Try
Restarbeiten mit und ohne Ausnahme
Unter VBA haben wir für Restarbeiten, die in jedem Fall, also auch beim Auftreten eines Fehlers zu erledigen sind, wie folgt untergebracht:
On Error Resume Fehler
'Fehlerauslösende Zeile
Ende:
'Restarbeiten
Exit Sub
Fehler:
'Fehlerbehandlung
Goto Ende
Wir haben also unter der Marke Ende Befehle untergebracht, die auch beim Ausbleiben eines Fehlers ausgelöst werden. Damit die Fehler-Marke nur erreicht wird, wenn tatsächlich ein Fehler auftritt, haben wir dieser die Exit Sub– beziehungsweise Exit Function-Anweisung vorangestellt. Damit die Aufräumarbeiten aber auch nach Auftreten eines Fehlers noch ausgeführt werden, haben wir am Ende der Fehlerbehandlung noch einen Verweis zur Marke Ende hinzugefügt.
Unter VB.NET benötigen wir dazu nur einen weiteren Zweig im Try…End Try-Konstukt. Dieser Zweig heißt Finally und wird immer am Ende eingebaut:
Sub TryCatchFinally Try Throw New FileNotFoundException Throw New DivideByZeroException() Catch ex As DivideByZeroException Debug.Print("Fehler: " & ex.Message) Catch ex As Exception Debug.Print("Fehler: " & ex.Message) Finally Debug.Print("Restarbeiten") End Try End Sub
Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Visual Basic Entwickler:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 200 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein: