User Tools

Site Tools


k11:k11.5:k11.5.1:start

11.5.1 Error detection and handling - Try, Finally and Catch

Especially when working with directories and files, errors can occur that are difficult to predict. They occur because, for example, files cannot be opened because part of the path specification is incorrect or they cannot be written to because the user does not have the necessary rights or a directory no longer exists to which a file is to be copied. However, it may also not be considered that a method requires an absolute (system) path and then a certain error is triggered. In all cases, error detection and error handling is required.

As usual in Gambas, the following keywords TRY, FINALLY and CATCH, the construct “IF ERROR THEN … ENDIF” and the event Application_Error() are used:

  • With 'TRY statement' an attempt is made to execute a statement that does not trigger an error indication in case of an error! This may seem sensible, but it must be remembered that the error is only concealed in this way!
  • The construct “IF ERROR THEN … ENDIF” is therefore used immediately after 'TRY statement' to find out whether the statement was executed correctly or not.
  • A Finally block is always executed at the end of a function or a procedure - whether an error occurred during the execution before or not. If there is an additional Catch block in the method, a Finally block must precede it.
  • A catch block is placed at the end at the end of a function or a procedure or after a finally block, introduced by the CATCH keyword. The Catch block is only executed if an error has occurred between the start of execution of a method and its end. If an error occurs during the execution of the Catch block, it is displayed.
  • A triggered error immediately moves up the call stack in the interpreter - until the error is observed or handled. This can be a TRY before a statement that covers the error in connection with “IF ERROR THEN …” or a Finally that also accepts an error and still wants to save data or a CATCH that handles the error covertly. If the interpreter does not find the keyword Try or a Finally or Catch block or the event Application_Error(), then the interpreter crashes!
  • In addition, you can also target the displayed error numbers (http://gambaswiki.org/wiki/error [1]) within an error handling to generate meaningful error messages in German, for example.
  • A special feature in this context is the use of the Application_Error() event. This event is triggered when an error occurs that does not originate from a Try statement or is handled by a Finally or Catch block.
  • However, there are also preventive strategies where certain errors (classes) can be excluded.

11.5.1.1 TRY

[1] Try TextArea1.Text = File.Load(".../help/help.txt")
[2] If Error Then 
[3]    Message.Error("The help file cannot be loaded.")
[4]    FHelp.Delete()
[5] Endif

If no error occurs when trying to load the help file, its contents are displayed in a text area. However, if the help file cannot be loaded, then the triggered error is not displayed - it is hidden. Therefore, in this case, lines 2 to 5 are executed, which at least inform about a present error. In the present case, the help file must not be displayed - but the programme continues to run.

11.5.1.2 FINALLY

In the next example, the Finally block is followed by a Catch block:

[1] Private Sub AddTextToFile(FilePath As String, Text As String)
[2]   
[3]   Dim hFile As File
[4]   
[5]   hFile = Open FilePath For Append
[6]   Finally
[7]     If Exist(FilePath) Then Close #hFile
[8]   Catch
[9]     Message.Error("Error:\n" & Error.Text & " in " & Error.Where)  
[10] End

In any case, the file is closed - the Finally block takes care of that. The (optional) Catch block would indicate an error occurring in lines 5 to 7.

11.5.1.3 CATCH

The following example uses only one catch block to display in a sufficiently differentiated manner all errors that occur with an appropriate error message:

[0] Public Sub btnHelpLibrary_Click()
[1]   Dim cl As Class
[2]   
[3]   cC = Component.Load(":gambasbook/LPathProject:1.2")
[4]   cl = Class.Load("Module1")
[5]   Object.Call(cl, cl.Symbols[0], Null)
[6]   Catch
[7]      Message.Error(Error.Text)
[8] 
[9] End

The two error messages below become understandable if, on the one hand, the library LPathProject cannot be loaded (error 1) and, on the other hand, Module1 is not available (error 2). In contrast, there was only the second error message when in the existing library the module with the specified name `Module1` did not exist.

B1

Figure 11.5.1.3.1: First error message

B2

Figure 11.5.1.3.2: Second error message

The catch block in the following example consistently catches all triggered errors and outputs a detailed error message. In addition, the last two procedures close the open files - if the file paths exist:

Public Sub btnAddTextToFile_Click()

  Dim sLogDir As String
  
  sLogDir = Desktop.DataDir &/ "gambasbook" &/ AppName 
  If Not Exist(sLogDir) Then Shell.MkDir(sLogDir)
  AddTextToFile(sLogDir &/ "rs232.log", "Time = " & Format(Now, "hh:nn:ss") & " - " & sTValue)
  Catch
    Message.Error("Error:\n" & Error.Text & " in " & Error.Where)
End

Public Sub btnGetTextFromFile_Click()

  Dim sLogPath As String
  
  sLogPath = Desktop.DataDir &/ "gambasbook" &/ AppName &/ "rs232.log"
  txaLog.Text = GetTextFromFile(sLogPath)
  Catch
    Message.Error("Error:\n" & Error.Text & " in " & Error.Where)
End

Private Sub AddTextToFile(FilePath As String, Text As String)
  
  Dim hFile As File
  
  hFile = Open FilePath For Append
  Finally
    If Exist(FilePath) Then Close #hFile
  Catch
    Message.Error("Error:\n" & Error.Text & " in " & Error.Where)  
End

Private Function GetTextFromFile(FilePath As String) As String

  Dim hFile As File
  Dim sLine, Text As String
  
  hFile = Open FilePath For Read  
   
  While Not Eof(hFile)
    Line Input #hFile, sLine
    Text &= sLine & "\n"
  Wend

  Return Text
  
  Finally
    If Exist(FilePath) Then Close #hFile
  Catch
    Message.Error("Error:\n" & Error.Text & " in " & Error.Where)
  
End

11.5.1.4 Event Application_Error()

Assumption: An error may be triggered for which neither a Try statement nor a Finally or Catch block is provided. This is exactly when you will use the Application_Error() event, for example, to write data into a file without fail or to delete a file under all circumstances before the programme ends. This event is triggered in the start class of the project. Only there can the event handling routine be located so that something happens and it must have the signature 'Static Public Sub Application_Error()'. The start class must not be a module.In the example, a lock file is created to prevent any attempt to create another instance of the application. If the programme ends without errors, the lock file is deleted. If the procedure RunATest() is executed, then the division by the divisor zero also takes place. An error is triggered, which is neither handled by a Try statement nor by a Finally or Catch block. The programme would crash - leaving the lock.file in the system. This would have the consequence that any further start of the programme would be prevented because there is already a lock file!

A way out is offered by the event Application_Error(), in whose event handling routine the lock.file is deleted - before all the lights go out … .

[1] ' Gambas class file
[2] 
[3] Public bFlag As Boolean = False
[4] 
[5] Public Sub _new()
[6]   
[7]   If Exist(Application.Path &/ ".lock.file") Then
[8]      Message.Warning(Subst("&1 '&2' &3", ("There is already an instance of"), Application.Name, "!"))
[9]      bFlag = False
[10]      FMain.Close()
[11]   Endif
[12] 
[13]   Shell "touch " & Application.Path &/ ".lock.file" Wait
[14] 
[15]   bFlag = True
[16]   
[17] End
[18] 
[19] Static Public Sub Application_Error() 
[20]   If Exist(Application.Path &/ ".lock.file") Then Kill Application.Path &/ ".lock.file" 
[21]   Wait   
[22] End 
[23] 
[24] Public Sub Form_Open()
[25]   FMain.Resizable = False
[26] End
[27] 
[28] Public Sub Form_Close()
[29]     If bFlag Then Try Kill Application.Path &/ ".lock.file"
[30]     FMain.Close()
[31] End
[32] 
[33] Public Sub btnTest_Click() 
[34]  RunATest() 
[35] End
[36] 
[37] Private Sub RunATest()
[38] 
[39]   Dim i As Integer
[40]   Dim q As Float
[41] 
[42]   For i = -2 To 2 
[43]     q = 5 / i 
[44]   Next 
[45] 
[46] End

B3

Figure 11.5.1.4.1: GUI

B4

Figure 11.5.1.4.2: Test error message.

Conclusion:

  • With the use of `TRY` and `IF ERROR THEN … ENDIF` you can not only detect an error but also handle it in many ways.
  • With `FINALLY` you are given the opportunity to always have an instruction executed; even in the case of an error.
  • The use of `CATCH` must be carefully considered, as an error that has occurred is only indicated but not immediately dealt with.
  • The use of the event Application_Error() is only useful in special cases.

Download

The website uses a temporary session cookie. This technically necessary cookie is deleted when the browser is closed. You can find information on cookies in our privacy policy.
k11/k11.5/k11.5.1/start.txt · Last modified: 28.09.2023 by emma

Page Tools