Cómo capturar errores genéricos (de todo tipo), tratamiento de excepciones, en Delphi y mostrar (o no) mensajes a medida, personalizados al usuario final. Explica la diferencia entre las cláusulas «except» y «finally». También muestra un listado de las clases de excepción (class exception) y la descripción de cada una de ellas.
- Estructuras básicas para la captura de errores o excepciones en Delphi.
- Ejemplos de capturas de errores en Delphi con Except ó Finally.
- Cómo guardar log de errores en una tabla con Delphi.
- Clases de excepciones en Delphi.
- EurekaLog para captura profesional de errores o excepciones en Delphi.
Estructuras básicas para la captura de errores o excepciones en Delphi
En primer lugar explicamos las dos estructuras básicas para la captura de errores en el lenguaje de programación Borland o Codegear Delphi:
- Except: en la estructura que mostramos a continuación sólo se ejecutará el código que va entre el «except» y el «end» si se produce un error. Si no se produce un error se continuará con la ejecución lógica del programa, si se produce un error se ejecutará el código entre el «except» y el «end» y se detendrá la ejecución lógica de la aplicación:
1 2 3 4 5 6 7 8 9 10 11 12 |
... begin ... //código que estará fuera de la captura de errores, normalmente //se colocará fuera el código que sepamos que no puede dar errror try //Aquí irá el código susceptible de provocar errores except //Colocaremos aquí el código que se ejecutará si se produce un error, //sólo se ejecutará si se produce un error end; end; |
- Finally: en la siguiente estructura el código que va entre el «finally» y el «end» se ejecutará siempre (tanto si se produce un error como si no). Este tipo de captura de errores suele ser usado para finalizar o liberar determinadas variables o estructuras que nos interese que siempre queden liberadas (tanto si se producen errores como si no):
1 2 3 4 5 6 7 8 9 10 11 |
... begin ... //código que estará fuera de la captura de errores, normalmente //se colocará fuera el código que sepamos que no puede dar errror try // Aquí irá el código susceptible de provocar errores finally //colocaremos aquí el código que se ejecutará tanto si //se produce un error como si no end; end; |
Ejemplos de capturas de errores en Delphi con Except ó Finally
Ejemplos con try…except…end
Por ejemplo, podemos acotar un código susceptible de que se produzca una división por cero con un «try» y un «except» de la siguiente forma, además, podemos personalizar el mensaje de error que se producirá:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
... var numero1, numero2, numero3 : integer; begin numero1 := 0; numero2 := 1; try numero3 := numero1 div numero2; ShowMessage ('Esta línea no se ejecutará pues se producirá el error.'); except on e : exception do begin ShowMessage ('Clase de error: ' + e.ClassName + chr(13) + chr(13) + 'Mensaje del error: ' + e.Message); end; end; end; |
Nota: si cambiamos el código dentro del Except por:
1 2 3 |
except raise; end; |
Mostrará el mensaje de error propio generado por Delphi, sin personalizar.
En el ejemplo anterior hemos utilizado el objeto «exception» que es la clase padre. Si queremos mostrar un mensaje aún más personalizado por cada tipo de error que se pueda prodicir utilizaremos el siguiente código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
... var numero1, numero2, numero3 : integer; begin numero1 := 0; numero2 := 1; try numero3 := numero1 div numero2; ShowMessage ('Esta línea no se ejecutará pues se producirá el error.'); except on e : EDivByZero do begin ShowMessage ('Ha intentado dividir un número por cero.'); end; else ShowMessage ('Se ha producido un error: ' + chr(13) + chr(13) + 'Clase de error: ' + e.ClassName + chr(13) + chr(13) + 'Mensaje del error: ' + e.Message); end; end; |
Ejemplos con Try…Finally…End
Un ejemplo utilizando «finally» (código que siempre se ejecutará tanto si hay error como si no):
1 2 3 4 5 6 7 8 9 10 11 |
procedure TformMenuPrincipal.actCuentasEmailExecute(Sender: TObject); var formulario : TformCuentas; begin formulario := TformCuentas.Create(Application); try formulario.ShowModal; finally formulario.Free; end; end; |
En este caso hemos utilizado un ejemplo que crea un formulario y lo muestra modal, si la línea «formualario.ShowModal» da un error (por cualquier causa) se ejecutará lo que haya en el «finally» y si no da error también, con lo cual, en este caso, nos aseguramos de que el formulario modal se libera siempre tras su ejecución.
Con lo cual utilizaremos «finally» siempre que nos interese que se ejecute código tanto si se produce un error como si no, por ejemplo cuando creamos un objeto y queramos que este se libere sea cual sea el resultado de la creación. Y utilizaremos «except» en los demás casos, cuando queramos que el código de error sólo se ejecute cuando éste se produzca.
Cómo guardar log de errores en una tabla con Delphi
Si queremos guardar los errores para poder consultarlos posteriormente en una tabla de una base de datos, podemos usar el siguiente código en la cláusula «except … End»:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
try //Código susceptible de provocar un error md.tcSpam.Open; except on e : exception do begin //ejecutamos procedure para insertar el mensaje de error en una tabla insertarLog (now, 'Error', E.Classname + ' : ' + E.Message); //mostramos el error al usuario raise; //realizamos otras tareas, como cerrar una tabla md.tcSpam.Close; end; end; |
En este caso «md.tcSpam.Open» es un TQuery con una consulta SQL asociada, si se produce algún error se ejecutará lo que haya dentro del «except», se ejecutará un procedimiento llamado «insertarLog» que, a su vez, inserta un registro en una base de datos para guardar los posibles errores de la aplicación. A continuación os mostramos el código del procedimiento «insertarLog»:
1 2 3 4 5 6 7 8 9 10 |
procedure insertarLog (fecha : TDateTime; tipo : string; mensaje : string); begin md.tLog.Open; md.tLog.Insert; md.tLogFECHA.Value := fecha; md.tLogTIPO.Value := tipo; md.tLogTEXTO.Value := mensaje; md.tLog.Post; md.tLog.Close; end; |
Donde md es el nombre del módulo de datos (TDataModule) en el que está el TTable «tLog» que apunta a una tabla de la base de datos con la siguiente estructura (MySQL):
1 2 3 4 5 6 7 |
CREATE TABLE `log` ( `ID` int(10) NOT NULL auto_increment, `FECHA` datetime default NULL, `TEXTO` varchar(255) default NULL, `TIPO` varchar(20) default NULL, PRIMARY KEY (`ID`) ); |
Aunque hemos de reconocer que no es conveniente utilizar funciones o procedimientos que puedan, a su vez, generar errores dentro de las cláusulas «except» ó «finally». Podríamos cambiar el código anterior por guardar el error en un fichero de texto plano, procedimiento que sería menos susceptible de generar errores que el de guardar en una base de datos.
Clases de excepciones en Delphi
A continuación os mostramos un listado de clases de excepciones de Borland Delphi 6:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<strong>Exception Base class</strong> EAbort Abort without dialog EAbstractError Abstract method error AssertionFailed Assert call failed EBitsError Boolean array error ECommonCalendarError Calendar calc error EDateTimeError DateTime calc error EMonthCalError Month calc error EConversionError Raised by Convert EConvertError Object convert error EDatabaseError Database error EExternal Hardware/Windows error EAccessViolation Access violation EControlC User abort occured EExternalException Other Internal error EIntError Integer calc error EDivByZero Integer Divide by zero EIntOverflow Integer overflow ERangeError Out of value range EMathError Floating point error EInvalidArgument Bad argument value EInvalidOp Inappropriate operation EOverflow Value too large EUnderflow Value too small EZeroDivide Floating Divide by zero EStackOverflow Severe Delphi problem EHeapException Dynamic memory problem EInvalidPointer Bad memory pointer EOutOfMemory Cannot allocate memory EInOutError IO error EInvalidCast Object casting error EInvalidOperation Bad component op EMenuError Menu item error EOSError Operating system error EParserError Parsing error EPrinter Printer error EPropertyError Class property error# EPropReadOnly Invalid property access EPropWriteOnly Invalid property access EThread Thread error EVariantError Variant problem |
EurekaLog para captura profesional de errores o excepciones en Delphi
En el siguiente artículo os mostramos qué es EurekaLog y cómo instalarlo y configurarlo para ser usado por los desarrolladores de Delphi, permitiendo mostrar una ventana cuando se produzca un error no capturado personalizada y con información avanzada: