VB -32: Errorhandling

Fallschirme bereitlegen...

Auch wenn wir unser Programm sehr ausgiebig testen, wird es uns doch einmal passieren, daß noch Fehler drin bleiben oder daß unser Anwender durch Fehlbedienung ein unvorhergesehenes Ereignis auslöst. In der Entwicklungsumgebung ist das relativ harmlos. Da taucht unser Debug-Fenster auf und wir können uns an die Suche machen.

Bei einem fertig kompilierten Programm kommt es jedoch in aller Regel zu einem Absturz. Wir sollten also Vorkehrungen treffen und unserem Programm eine Fallschirm beipacken, damit die Landung nicht ganz so hart wird.

Wir können dies tun, indem wir am Anfang einer Prozedur dem Programm sagen, was es im Falle eines Fehlers machen soll, z.B.:

     Private Sub Form_Load()
     On Error GoTo Form_Load_ErrorHandler
 

Form_Load_ErrorHandler bezeichnet hier eine Sprungmarke, die wir in unserem Programm setzen müssen. Üblicherweise schreibt man die eigentliche Fehlerbehandlungsroutine dann an das Ende einer Prozedur. Komplett sieht das dann für unser Form_Load-Ereignis so aus:

     Private Sub Form_Load()
     On Error GoTo Form_Load_ErrorHandler

     Dim i As Integer
        For i = 1 To 8             'rote Kugeln
            Load imgKugelX(i)      'benötigte Anzahl Kugeln laden
            imgKugelX(i).Left = imgKugelX(i - 1).Left + imgKugelX(i).Width * 1.2
            'Kugeln positionieren
        Next
        For i = 1 To 8             'blaue Kugeln
            Load imgKugelY(i)      'benötigte Anzahl Kugeln laden
            imgKugelY(i).Left = imgKugelY(i - 1).Left + imgKugelY(i).Width * 1.2
            'Kugeln positionieren
        Next

        Exit Sub

     Form_Load_ErrorHandler:

        Select Case MsgBox("Fehler in Form_Load", vbAbortRetryIgnore + _
         vbExclamation, " Fehlermeldung")
            Case vbAbort
                Resume Exit_Form_Load
            Case vbRetry
                Resume
            Case vbIgnore
                Resume Next
        End Select

     Exit_Form_Load:
     End Sub
 

Vor die Sprungmarke für die Fehlerbehandlung (Form_Load_ErrorHandler:) müssen wir stets einen "normalen" Ausgang aus unserem Unterprogramm definieren (Exit Sub), denn die nachfolgenden Zeilen sollen ja nur im Falle eines Fehlers ausgeführt werden.

In diesem Beispiel überlassen wir es dem Anwender, wie weitergemacht werden soll (Wiederholen, Ignorieren, Abbruch). Wir können auch noch ein paar weitere Informationen an die MessageBox übergeben, damit der Anwender eine Entscheidungsgrundlage hat:

        Select Case MsgBox("Fehler " & Err.Number & ": " & vbCrLf & _
         Err.Description & vbCrLf &  "aufgetreten in Form_Load", _
         vbAbortRetryIgnore + vbExclamation, " Fehlermeldung")
 

Err.Number übergibt die Fehler-Nummer. In der Onlinehilfe gibt es eine Liste, in der wir nachschlagen können, um welchen Fehler es sich handelt.

Err.Description gibt den Fehlerbeschreibungstext an. Damit kann unser Anwender meist schon etwas mehr anfangen.

Um es auszuprobieren, können wir an jeder beliebigen Stelle einen Fehler simulieren, z.B.:

        For i = 1 To 8             'rote Kugeln
            Load imgKugelX(i)      'benötigte Anzahl Kugeln laden
            imgKugelX(i).Left = imgKugelX(i - 1).Left + imgKugelX(i).Width * 1.2
            'Kugeln positionieren
        Next
        Err.Raise 340              'künstlich Fehler erzeugen
 

Dieser Befehl tut so, als würde der Fehler 340 auftreten und zeigt uns das Funktionieren unserer Fehlerroutine. Bestimmte Fehler, mit denen wir rechnen müssen, wie z.B. der Versuch auf eine CD zu schreiben oder zu drucken, wenn kein Drucker angeschlossen ist, können wir von vornherein einer Sonderbehandlung unterziehen und dem Anwender noch zusätzliche Tips geben.

Eine Fehlerroutine sollte in jeder Prozedur stehen, soweit sie in irgendeiner Form fehleranfällig sein könnte (auch wenn wir es uns zunächst nicht vorstellen können ). Ich hab unser Projekt mal komplett damit ausgestattet.

Beispielprojekt laden

Wollen wir, daß bestimmte Fehler grundsätzlich ignoriert werden, weil sie zwar vorkommen können, aber für den weiteren Ablauf unerheblich sind, können wir dies, indem wir dem Programm sagen, es soll mit dem nächsten Befehl weitermachen, z.B.:

            On Error Resume Next
            Label1.Font = "Kinder"
 

In diesem Beispiel habe ich Label1 eine Schriftart (Kinder) zugewiesen, die nicht unbedingt auf dem Zielrechner vorhanden sein wird. Es würde ohne diese Schriftart unweigerlich eine Fehlermeldung auftreten. Durch den Zusatz "Resume Next" macht das Programm einfach mit dem nächsten Befehl weiter. Wollen wir, daß danach wieder unsere Fehlerroutine greift, müssen wir sie erneut setzen:

            On Error Resume Next
            Label1.Font = "Kinder"
            On Error GoTo ErrorHandler
 

Wollen wir eine Fehlerbehandlungsroutine für einen Teil des Programms ganz außer Gefecht setzen, definieren wir eine Sprungmarke 0, z.B.:

            On Error GoTo 0
            Befehle...
 

Dies bleibt solange wirksam, bis das Programm auf eine neue Fehlerbehandlungsanweisung trifft.

Gerade bei größeren Programmen ist unsere Fehlerbehandlunsgroutine evtl. noch nicht aussagekräftig genug, um per Ferndiagnose (z.B. per Online in einem anderen Teil der Erde) das Problem zu finden. Hier können wir weiter ergänzen, indem wir nicht nur die Fehlermeldung selber angeben, sondern auch ganz genau in welcher Zeile das Problem auftritt. Dazu müssen wir zunächst unsere Zeilen numerieren:

     Sub Sound(WAVDatei As String)
     1: On Error GoTo Sound_ErrorHandler

     2: '-------------------- Code Body Starts --------------------
     3: Dim rc As Long
     4:    rc = sndPlaySound(WAVDatei, 1)
     5: '--------------------- Code Body Ends ---------------------

     6:    Exit Sub

     Sound_ErrorHandler:

        Select Case MsgBox("Fehler " & Err.Number & ": " & vbCrLf & _
         Err.Description & vbCrLf & vbTab & vbTab & "aufgetreten in Zeile " _
         & Erl & vbCrLf & "in " & App.Title & ": Sound", _
         vbAbortRetryIgnore + vbExclamation, App.Title & " Fehlermeldung")
            Case vbAbort
     8:            Resume Exit_Sound
     9:        Case vbRetry
     10:            Resume
     11:        Case vbIgnore
     12:            Resume Next
     13:    End Select

     Exit_Sound:
     End Sub
 

Durch den Zusatz "Erl" wird uns auch noch zusätzlich die Zeilennummer angezeigt, in der der Fehler auftritt.

Beispielprojekt laden

Jetzt landet unser Anwender auf jeden Fall sanft, wenn das Programm abstürzt (auch wenn er vielleicht nicht ganz glücklich sein wird ) und wir können versuchen, den Fehler bei uns nachzuvollziehen und auszumerzen.

Anmerkung: Das Einfügen von solchen Fehlerroutinen ist recht mühsam, vor allem wenn es sich um umfangreiche Programme handelt. Ich hab es mir einfach gemacht und hab das VB-AddIn Voodoo Coder benutzt, das ein Modul mit einem Klick komplett mit vordefinierten Fehlerroutinen ergänzt. Die "Templates" können den eigenen Bedürfnissen angepaßt werden und können dann entweder mit oder ohne Zeilennummern eingefügt werden.

zurück Index weiter


© Copyright 1998-2000 J.Behling EMail schreiben ABC-Ware's Homepage
Weitergabe und Druck (auch in Teilen, mit Ausnahme von Privatgebrauch) ohne ausdrückliche Genehmigung der Autorin untersagt.