Error Handling

 

.NET Error Handling with the Try / Catch / Finally Block

 

Error handling is essential to all professional applications. Any number of run-time errors can occur, and if your program does not trap them, the VB.NET default action is to report the error and then terminate the program (often resulting in the end user calling you and complaining, "Your program kicked me out!"). By placing error-handling code in your program, you can trap a run-time error, report it, and possibly let the user continue. In any case, simply allowing the program to "crash" is not acceptable. You should generally place error-handling code in any Sub or Function that contains code that could potentially cause an error, such as code that accesses files or databases.

 

In VB.NET, error trapping is accomplished using the Try / Catch / Finally block. The general syntax is as follows:

 

Try

' main block of code here

[Catch exception_variable as Exception_Type_1

' code for handling Exception_Type_1]

[Catch exception_variable as Exception_Type_2

' code for handling Exception_Type_2]

. . .

[Catch exception_variable as Exception_Type_n

' code for handling Exception_Type_n]

[Finally

' code that will execute regardless of whether or not an error occurs

]

End Try

 

When using the Try block, you can optionally have any number of Catch clauses. If an error occurs within the main block of code, control transfers to the appropriate Catch clause and the code in that Catch block will be executed. If the optional Finally block is present, any code within the Finally block will be executed, regardless of whether or not an error occurred.

 

The sample error-trapping demo program shows you various options for handling possible problems that might occur when trying to open a file on a flash drive.


The VB project code for the sample program can be downloaded here.

 

On my test system, my USB flash drive shows up as drive "E:"; your drive letter may vary (and thus you should modify the code of the sample program accordingly). To test the sample program, you should have a USB flash drive that initially does NOT contain a file called "junk.txt". If your system assigns a drive letter other than "E:" to your flash drive, you should change all occurrences of "E:" in the sample program code to the appropriate letter.

 

 

As an initial test, take your flash drive out.


Upon running the program, you will see a "main menu" come up with five choices. Enter 1 (for "Crash"):

 

When you enter "1", the Sub Crash is called, which contains no error-handling code:

 

Private Sub Crash()

 

FileOpen(1, "E:\JUNK.TXT", OpenMode.Input)

Console.WriteLine("File was opened successfully.")

FileClose(1)

 

Console.WriteLine()

Console.WriteLine("Press Enter to Return to Menu.")

Console.ReadLine()

ShowMenu()

 

End Sub

 

As soon as the program tries to do the "FileOpen" (for a file on the flash drive that is not present), the error occurs. If running the program from the VB 2010 IDE, the system will return you to the code and will highlight the offending line of code in yellow, as seen in the top screen-shot on the right. If running from the stand-alone executable, the user will encounter a message similar to the bottom screen-shot on the right, and the console window will close (abruptly ending the program). (Note: If you test the program from the executable and get this Microsoft error message, just click the "Don't Send" message to close it.)

 

 

With the flash drive still removed, re-run the program, but this time choose "2" from the menu. This will call the Sub "HandleGeneralError", which is coded as follows:

 

Private Sub HandleGeneralError()

 

Try

FileOpen(1, "E:\JUNK.TXT", OpenMode.Input)

Console.WriteLine("File was opened successfully.")

FileClose(1)

Catch ex As Exception

Console.WriteLine()

Console.WriteLine("Error: " & ex.Message)

Finally

Console.WriteLine()

Console.WriteLine("Press Enter to Return to Menu.")

Console.ReadLine()

ShowMenu()

End Try

 

End Sub

 

Now, when the program tries to open the file, the flow of control will branch to the "Catch" block, and error-handling code there will be executed. Note that you can use ex.Message to report the error to the user. In the situation with the missing flash drive, the system reports "Could not find part of the path 'E:\JUNK.TXT'".

 

 

 

Now place the flash drive in the computer (assuming the flash drive still does NOT contain the file "JUNK.TXT"). Select option "2" again, and notice that a different error message is reported ("Could not find file 'E:\JUNK.TXT'".)

 

Now choose option "3" from the menu. This will call the Sub "HandleSpecificError", which is coded as follows:

 

Private Sub HandleSpecificError()

 

Try

FileOpen(1, "E:\JUNK.TXT", OpenMode.Input)

Console.WriteLine("File was opened successfully.")

FileClose(1)

Catch ex As System.IO.FileNotFoundException

Console.WriteLine()

Console.WriteLine( _

"Error: File 'JUNK.TXT' was not found.")

Catch ex As System.IO.DriveNotFoundException

Console.WriteLine()

Console.WriteLine( _

"Error: Drive 'E:' could not be accessed.")

Catch ex As System.IO.DirectoryNotFoundException

Console.WriteLine()

Console.WriteLine( _

"Error: Directory 'E:\' could not be accessed.")

Catch ex As Exception

Console.WriteLine()

Console.WriteLine("Error: " & ex.Message)

Finally

Console.WriteLine()

Console.WriteLine("Press Enter to Return to Menu.")

Console.ReadLine()

ShowMenu()

End Try

 

Note that this Sub contains multiple "Catch" blocks, each with the purpose of trapping a specific type of error (FileNotFoundException, DriveNotFoundException, DirectoryNotFoundException) and each containing its own custom message, along with a catch-all for the generic "Exception" which uses the standard ex.Message.

 

To demonstrate the not-so-common case where you want to intentionally ignore an error, choose option "4" from the menu. This will call the Sub "IgnoreError", which is coded as follows:

 

Private Sub IgnoreError()

 

Try

 

Try

FileOpen(1, "E:\JUNK.TXT", OpenMode.Input)

Console.WriteLine("File was opened successfully.")

FileClose(1)

Catch ex As Exception

' leave empty to effectively ignore any error

End Try

 

Console.WriteLine()

Console.WriteLine("We don't know if file was " & _

"opened successfully or not.")

 

Catch ex As Exception

' nothing to really catch here

 

Finally

Console.WriteLine()

Console.WriteLine("Press Enter to Return to Menu.")

Console.ReadLine()

ShowMenu()

 

End Try

 

End Sub

 

Note that we have an inner Try block nested within the outer Try block. The inner Try block has an empty Catch block, which basically will trap the "FileOpen" error, but since there is no code associated with it, no error message will be reported. Following the inner Try block (but still within the outer Try block), the message "We don't know if file was opened successfully or not." is displayed.

 

 

To complete your testing, place an empty file called "JUNK.TXT" on your flash drive. This can be done by navigating to your flash drive in Windows (on Win XP, you can start with "My Computer", open "E" drive (or whatever letter the system assigned to your flash drive). Once the drive window is open, right-click on a white area of the window, and select "New", then "Text Document". Rename the newly created text document "JUNK.TXT".

 

Now, with the flash drive inserted and containing a file called "JUNK.TXT", any of the options "1" through "4" should report "File was opened successfully."

 

 

 

"Old School" Error Handling with the On Error Statement

 

Pre-.NET versions of Visual Basic (VB1 thru VB6) did not use Try / Catch / Finally blocks, but rather used the "On Error" statement for error handling. To maintain compatibility, VB.NET still supports the "On Error" statement. The following programming example is a variation of the program above that uses the "On Error" way of error handling instead of "Try / Catch / Finally". NOTE: The two different methods of error handling ("On Error" and "Try / Catch / Finally") CANNOT be used within the same Sub or Function however, you can use either method in different Subs and Functions within the same program.

 

In this section, we will look at the following statements:

 

On Error GoTo label

Specifies a label in the Sub or Function that will be branched to if an error occurs.

On Error GoTo 0

Turns OFF the current error handler.

On Error Resume Next

Causes an error to be ignored and continue with the next statement in the program flow.

 

 

As above, the sample error-trapping demo program below shows you various options for handling possible problems that might occur when trying to open a file on a flash drive.


The VB project code for the sample program can be downloaded here.

 

On my test system, my USB flash drive shows up as drive "E:"; your drive letter may vary (and thus you should modify the code of the sample program accordingly). To test the sample program, you should have a USB flash drive that initially does NOT contain a file called "junk.txt". If your system assigns a drive letter other than "E:" to your flash drive, you should change all occurrences of "E:" in the sample program code to the appropriate letter.

 

 

As an initial test, take your flash drive out.


Upon running the program, you will see a "main menu" come up with six choices. Enter 1 (for "Crash"):

 

When you enter "1", the Sub Crash is called, which contains no error-handling code:

 

Private Sub Crash()

 

FileOpen(1, "E:\JUNK.TXT", OpenMode.Input)

Console.WriteLine("File was opened successfully.")

FileClose(1)

 

Console.WriteLine()

Console.WriteLine("Press Enter to Return to Menu.")

Console.ReadLine()

ShowMenu()

 

End Sub

 

As soon as the program tries to do the "FileOpen" (for a file on the flash drive that is not present), the error occurs. If running the program from the VB 2010 IDE, the system will return you to the code and will highlight the offending line of code in yellow, as seen in the top screen-shot on the right. If running from the stand-alone executable, the user will encounter a message similar to the bottom screen-shot on the right, and the console window will close (abruptly ending the program). (Note: If you test the program from the executable and get this Microsoft error message, just click the "Don't Send" message to close it.)

 

 

With the flash drive still removed, re-run the program, but this time choose "2" from the menu. This will call the Sub "HandleGeneralError", which is coded as follows:

 

Private Sub HandleGeneralError()

 

On Error GoTo GeneralErrorHandler

 

FileOpen(1, "E:\JUNK.TXT", OpenMode.Input)

Console.WriteLine("File was opened successfully.")

FileClose(1)

 

ReturnToMenu:

Console.WriteLine()

Console.WriteLine("Press Enter to Return to Menu.")

Console.ReadLine()

ShowMenu()

Exit Sub

 

GeneralErrorHandler:

Console.WriteLine()

Console.WriteLine("The following error has occurred: " & vbNewLine _

& "Error # " & Err.Number & " - " & Err.Description)

GoTo ReturnToMenu

 

End Sub

 

Now, when the program tries to open the file, the flow of control will branch to the "GeneralErrorHandler" label, and error-handling code there will be executed. Note that you can use Err.Number and Err.Description to report the error to the user. In the situation with the missing flash drive, the system reports "Could not find part of the path 'E:\JUNK.TXT'". To wrap things up, note that after the error is reported, we branch back to the line labeled "ReturnToMenu", so that the user can continue using the program.

 

 

Now place the flash drive in the computer (assuming the flash drive still does NOT contain the file "JUNK.TXT"). Select option "2" again, and notice that a different error message is reported ("Could not find file 'E:\JUNK.TXT'".)

 

Now choose option "3" from the menu. This will call the Sub "CancelErrorHandling", which is coded as follows:

 

Private Sub CancelErrorHandling()

 

On Error GoTo GeneralErrorHandler

 

'cancel above error handler

On Error GoTo 0

 

FileOpen(1, "E:\JUNK.TXT", OpenMode.Input)

Console.WriteLine("File was opened successfully.")

FileClose(1)

 

ReturnToMenu:

Console.WriteLine()

Console.WriteLine("Press Enter to Return to Menu.")

Console.ReadLine()

ShowMenu()

Exit Sub

 

GeneralErrorHandler:

Console.WriteLine()

Console.WriteLine("The following error has occurred: " & vbNewLine _

& "Error # " & Err.Number & " - " & Err.Description)

GoTo ReturnToMenu

 

End Sub

 

This Sub is identical to the Sub "HandleGeneralError", except that it contains the line On Error GoTo 0, turns off, or cancels, a previous On Error statement. The result of this is the same as the "Crash" example above. You would typically use "On Error GoTo 0" while you are testing a program, so that you can determine exactly what statement caused the error when the program crashes in the design environment. You would typically remove this statement before you did a final compile.

 

Now choose option "4" from the menu. This will call the Sub "HandleSpecificError", which is coded as follows:

 

Private Sub HandleSpecificError()

 

On Error Resume Next

 

FileOpen(1, "E:\JUNK.TXT", OpenMode.Input)

 

Select Case Err.Number

Case 0

Console.WriteLine("File was opened successfully.")

FileClose(1)

Case 53

Console.WriteLine()

Console.WriteLine("Error: File 'JUNK.TXT' was not found.")

Case 76

Console.WriteLine()

Console.WriteLine("Error: Drive not found.")

Case Else

Console.WriteLine()

Console.WriteLine("The following error has occurred: " & vbNewLine _

& "Error # " & Err.Number & " - " & Err.Description)

End Select

 

Console.WriteLine()

Console.WriteLine("Press Enter to Return to Menu.")

Console.ReadLine()

ShowMenu()

 

End Sub

 

Note that this Sub starts off with the statement "On Error Resume Next", which tells the system to continue processing with the next statement even if an error is encountered. However, the Err.Number value is still set, so you can test this and perform your own custom error handling, which is done with a Select Case structure in this example. An Err.Number value of 0 is good; it means an error did not occur. In this example we are also testing for errors 53 (file not found) and 76 (path not found). The "Case Else" portion of the Select Case statement allows us to provide a "catch-all", which has the same code as the general error handler. For a list of trappable errors, the following link can be used:

http://msdn.microsoft.com/en-us/library/aa264975%28v=VS.60%29.aspx

 

To demonstrate the not-so-common case where you want to intentionally ignore an error, choose option "5" from the menu. This will call the Sub "IgnoreError", which is coded as follows:

 

Private Sub IgnoreError()

 

On Error Resume Next

 

FileOpen(1, "E:\JUNK.TXT", OpenMode.Input)

FileClose(1)

 

Console.WriteLine()

Console.WriteLine("We don't know if the file was opened successfully.")

 

Console.WriteLine()

Console.WriteLine("Press Enter to Return to Menu.")

Console.ReadLine()

ShowMenu()

 

End Sub

 

Note that this Sub also starts off with the statement "On Error Resume Next", however, there is no "follow up" to test the value of Err.Number. So although you have the code here to open the file, you don't know at that point if the file was opened successfully. Be advised that it is not good practice to ignore errors unless you have specific reason to do so.

 

 

To complete your testing, place an empty file called "JUNK.TXT" on your flash drive. This can be done by navigating to your flash drive in Windows (on Win XP, you can start with "My Computer", open "E" drive (or whatever letter the system assigned to your flash drive). Once the drive window is open, right-click on a white area of the window, and select "New", then "Text Document". Rename the newly created text document "JUNK.TXT".

 

Now, with the flash drive inserted and containing a file called "JUNK.TXT", any of the options "1" through "4" should report "File was opened successfully."