Como utilizar rutinas de error en los formularios

4,568 views
Skip to first unread message

foxteban

unread,
Mar 31, 2012, 7:14:47 PM3/31/12
to Comunidad de Visual Foxpro en Español
Hola Grupo

Haber si me orientan un poco. Nunca he usado la rutina para controlar
errores en los formularios.
Se de la funcion ON ERROR. Mi pregunta es:
- En donde debo poner la funcion ON ERROR en el form ?
- Que lineas de codigo debo poner y en donde ?
- Como se utiliza el evento ERROR de los form ? Que debo escribir
alli ?
- Hay que especificar algun numero de error para los distintos
errores ?
- La funcion AERROR() en que lugar la invoco.
- Hay una rutina general para todo el programa o hay que poner una por
cada formulario ?
- etc.

Si hay alguna rutina o explicacion en internet, citenme la pagina.

Bueno gente, desde ya agradecido.

Les dejo saludos

Esteban



Walter R. Ojeda Valiente

unread,
Mar 31, 2012, 7:34:51 PM3/31/12
to publice...@googlegroups.com
ON ERROR puedes utilizarlo al inicio de tu programa principal (por ejemplo: MAIN.PRG) para decirle al VFP cual será la rutina encargada de manejar todos los errores que puedan ocurrir.

Por ejemplo:

ON ERROR do ATRAPARERRORES with Error(), Message(), Message(1), Program(), LineNo(1)

Y luego creas un procedimiento llamado ATRAPARERRORES con esos parámetros:

PROCEDURE ATRAPARERRORES
LParameters tnErrorNro, tcMensaje1, tcMensaje2, tcPrograma, tnLineaNro

   * Manejas los errores aquí

RETURN

Entonces, cada vez que el VFP encuentre un error en tu código en lugar de mostrarte un mensaje con ese error ejecutará el procedimiento ATRAPARERRORES donde tú puedes decidir que hacer cuando ocurre cada error.

Sin embargo, mucho mejor que usar ON ERROR suele ser utilizar la construcción TRY...ENDTRY, pero es mayormente cuestión de gustos.

Saludos.

Walter.




> Date: Sat, 31 Mar 2012 16:14:47 -0700
> Subject: [vfp] Como utilizar rutinas de error en los formularios
> From: esteban...@hotmail.com
> To: publice...@googlegroups.com

Luis Maria Guayan

unread,
Mar 31, 2012, 7:42:18 PM3/31/12
to publice...@googlegroups.com
A partir de VFP8 es recomendable utilizar la estructura TRY ... CATCH .. ENDTRY para capturar los errores.

De todos modos, los formularios tienen un método Error() que se ejecuta cuando existe un error en el formulario. Lo puedes utilizar sin problemas, si no implemetas tus rutinas de error con TRY ... CATCH ...

Luis María Guayán
Tucumán, Argentina
_________________________
http://www.PortalFox.com
Nada corre como un zorro
_________________________

foxteban

unread,
Mar 31, 2012, 10:03:03 PM3/31/12
to Comunidad de Visual Foxpro en Español
Gracias Walter y Luis Maria

Luis en lo que tu me comentas, del metodo ERROR() en los formularios,
que debo escribir alli, por ejemplo ?
Gracias.

Esteban

integral

unread,
Mar 31, 2012, 11:11:47 PM3/31/12
to Comunidad de Visual Foxpro en Español

Amigo Foxteban :

Te contare que en mi caso vengo utilizando el ON ERROR en VFP 9.0 .
Para ello en cada formulario en el metodo LOAD tengo el siguiente
codigo.

**************************************************
* ESTABLECER CONTROL DE ERRORES *
**************************************************
On Error DO ERRORES With ;
Error( ), Message( ), Message(1), Program( ), LineNo( )
Set Procedure To C:\CONTROL90\APLICACION\PRGS\Rutinas2.prg

Como veras en RUTINAR2.PRG esta el codigo que genera el mensaje de
error con las opciones que tu desees implementar como por ejemplo ahi
mismo crear una rutina que cree un tabla en donde se guarde los
errores generados esta idea lo tome del Sr. MIKE LEWIS

Espero haber respondido a tu pregunta.

Saludos,

Gabriel
(Lima-Perú)

foxteban

unread,
Mar 31, 2012, 11:44:37 PM3/31/12
to Comunidad de Visual Foxpro en Español
Bueno Amigos
Gracias a todos, ya lo soluciones con la fucnion de ON ERROR, como
Uds me lo indicaron.
Realmente esta muy buena, soy franco en decir que nunca lo habia
utilizado, pero es utilisimo para continuar con el programa despues de
un error y no dejar colgado al usuario.
Nuevamente gracias

Ahora hago otra consulta:
Como hago para cerrar un programa que llama a otro programa pero una
vez ingresado en el ultimo programa se cierre al que los llamo.
Es un Gestor que incia las aplicaciones restantes ya sea un iva, un
contable, un sueldo, etc. Necesito hacer esto por que en los programas
abiertos me hace referencia al programa gestor que los llamo, no se
porque pero me esta ocurriendo.

Bueno gente
Les dejo saludos
Esteban

Victor Espina

unread,
Apr 1, 2012, 10:52:28 AM4/1/12
to publice...@googlegroups.com
Como bien indica Luis Maria, el uso de ON ERROR es una herencia de las versiones de VFP anteriores a la introduccion de TRY CATCH.  En las aplicaciones modernos de VFP se recomienda ampliamente el uso de un TRY-CATCH general, que funcione como un fail-safe ante cualquier error no capturado localmente dentro de la aplicacion, y bloques TRY-CATCH locales para operaciones especificas.

Por ejemplo, un TRY CATCH global podria lucir asi:

PROCEDURE Main
 *
 * Seteos y configuracion inicial del programa

 * Ciclo de eventos principal
TRY
  DO FORM formularioPrincipal
  READ EVENTS

CATCH TO ex
  mostrarMensajeError(ex)

FINALLY
 CLEAR EVENTS

ENDTRY

TRY
 CLOSE ALL
 SQLDISCONNECT(0)
CATCH TO ex
 * Si ocurre un error durante el CLOSE ALL simplemente lo obviamos
ENDTRY

RETURN

PROCEDURE mostrarMensajeError(poEx)
 MESSAGEBOX("Ha ocurrido un error: " + poEx.Message,"Error",0)
ENDPROC


Eso causaria que cualquier mensaje de error ocurrido en la aplicacion fuese capturado por el CATCH en el programa principal y se procederia a mostrar al usuario un mensaje con el error ocurrido y se finalizaria la aplicacion.

Lo cual me lleva a mi segundo punto: es PESIMA idea permitir que el usuario continue con la ejecucion del programa luego de un error no controlado.  Entendemos por un error no controlado aquel error para el cual no estabamos explicitamente preparados en nuestro programa (explicare un poco mas esto mas adelante).  Cuando un error no controlado sucede, lo mas sano es finalizar la aplicacion en ese mismo momento. Porque? porque si dejamos que el usuario continue con la ejecucion del programa podriamos correr el riesgo de que el error ocurrido haya creado una situacion de inestabilidad en el codigo del programa (por ejemplo, dejando en NULL una variable que normalmente se espera contenga algun valor) que podria resultar en data incorrecta en nuestra base de datos.

Adicionalmente, mi experiencia me ha indicado que los unicos errores que un usuario final reporta son aquellos que no le permiten trabajar; si el usuario ve que puede ignorar el error y seguir trabajando, su respuesta a la pregunta "como se comporta el sistema?" sera siempre "perfecto!! sin problemas...".

Ahora, cuando un error es "esperado"? cuando podemos anticiparlo. Por ejemplo, si tenemos una rutina que copia un archivo de una ruta a otra, podemos anticipar que la operacion de copiado puede fallar por muchas razones ajenas a nuestra aplicacion.  Supongamos que tenemos una funcion copiarArchivo(), que toma dos parametros:

PROCEDURE copiarArchivo(pcOrigen, pcDestino)
 COPY FILE (pcOrigen) TO (pcDestino)
ENDPROC

En esta version de la funcion, si la ruta contenida en pcDestino no estuviera accesible o fuese solo/lectura, la rutina fallaria y el error seria capturado por el ON ERROR o el TRY-CATCH general, lo cual en el mejor de los casos terminaria con un mensaje de error que finaliza la aplicacion y en el peor de los casos en un mensaje de error que le informa al usuario que la copia no funciono, pero que NO LE INDICA al programa que invoco a coparArchivo() que efectivamente la copia no funciono.

Por esto, una mejor version de la funcion seria esta:

PROCEDURE copiarArchivo(pcOrigen, pcDestino)
 LOCAL lResult
 lResult = .F. 
 TRY
  COPY FILE (pcOrigen) TO (pcDestino)
  lResult = .T.
 CATCH TO ex
  mostrarMensajeError(ex)
 ENDTRY
 
 RETURN lResult
ENDPROC

En esta version estamos reconociendo que PODRIA ocurir un error al realizar la copia y que, de ser asi, la funcion se encargara de notificar tanto al usuario (con la llamada a mostrarMensajeError) como al programa que invoco la funcion (con el RETURN lResult).  Asi, en nuestro codigo podriamos hacer esto:

IF NOT coparArchivo(cFuente, cDestino)
 RETURN
ENDIF

Un comentario sobre el ON ERROR, que me vino a la mente por un codigo que vi en este hilo:  no tiene sentido colocar un ON ERROR en el evento LOAD de las formas, pues el ON ERROR no se ve afectado por las sesiones de datos. Por esa razon, el ON ERROR se coloca al inicio del programa principal ya que tiene alcance sobre toda la aplicacion.

Otra buena idea es usar el evento Error de los formularios, especialmente si basamos todos nuestros formularios en una unica clase base personalizada.  Programar el evento Error nos da la ventaja de que si ocurre un error no esperado dentro del formularo, el mismo solo afectara al formulario actual por lo que nos seria posible mostrar el error y cerrar ESE formulario solamente en lugar de obligar al usuario a salirse de la aplicacion completa.

Un esquema ideal de manejo de errores seria asi:

a) Si ocurre un error esperado, el mismo se maneja localmente en la funcion o procedimiento y no afecta la ejecucion del programa

b) Si ocurre un error inesperado a nivel del formulario, el mismo sera interceptado por el evento Error, se le notificara al usuario el error ocurrido y se cerrara el formulario afectado solamente.

c) Si ocurre un error inesperado FUERA de un formulario o dentro del evento Error de la forma, el mismo seria interceptado por el TRY-CATCH general, notificado al usuario y se finalizaria la aplicacion inmediatamente.


Otra muy buena idea con respecto al manejo de errores es llevar un log de los mismos, de preferencia en un archivo de texto.  Se que es mucho mas facil escribir en un DBF pero el problema con los DBFs es que necesitaras crear una aplicacion especial para leer esos archivos y ver el contenido (pues en los clientes no tendras fox instalado).

En mi opinion, una forma mas practica es usar archivos de texto donde cada linea corresponda a un error registrado, indicando datos como fecha/hora del error, usuario activo, estacion, objeto donde ocurrio (procedimiento, forma u otro), la linea dentro del programa donde ocurrio el error (si fuese posible obtener esa informacion), el stack-trace y la descripcion del error ocurrido. La ventaja del archivo log en texto es que todo lo que necesito para leerlo es el Notepad, que viene instalado en todos los Windows.

Justamente este tema del log es otra buena razon para tener una unica funcion para notificar errores al usuario, pues en dicha funcion debemos no solamente notificar al usuario el error ocurrido sino registrar el mismo en el log de errores de la aplicacion e, incluso, ofrecer al usuario la posibilidad de notificar el error al departamento tecnico y/o fabricante enviando los datos del mismo por correo (esta funcion es MUY util sobre todo con clientes que no viven en el area donde residimos). Y que seria aun mejor que la posibilidad de que el usuario nos envie los datos del error por correo? que el correo incluya una IMAGEN de la pantalla al momento de ocurrir el error!!  Hay rutinas gratuitas que permiten capturar la pantalla ANTES de que mostremos el mensaje con el error y convertirla a JPG.

Para finalizar tengo que anadir que esto del manejo de errores puede llegar a ser un poco complicado si no se estructura correctamente.  Un problema muy particular con el TRY-CATCH es que puede ser muy dificil ofrecer informacion sobre en DONDE ocurrio el error, pues al contrario del ON ERROR,  para cuendo entra en juego el CATCH general, ya VFP perdio la posicion que tenia dentro del Stack de ejecucion, por lo que ya no es posible saber DONDE fue que ocurrio el error.  Afortunadamente hay tecnicas para solucionar estos problemas, pero hay que investigar un probar un poco antes de implementarlas.

Les recomiendo ampliamente las siguientes lecturas para profundizar en el tema del manejo de errores en VFP:


Saludos

Victor Espina

Dario_El_Cyber_Gaucho

unread,
Apr 1, 2012, 11:06:26 AM4/1/12
to publice...@googlegroups.com

Dario_El_Cyber_Gaucho

unread,
Apr 1, 2012, 2:58:52 PM4/1/12
to publice...@googlegroups.com
Victor de usar la idea global si coloco

el programa ppal en el proyecto es menu0


Menu0.pg

* Seteos y configuracion inicial del programa

public xerror

TRY
* LLamo al menu ppal desde menu0
do menu
read event

CATCH TO xerror

*en errores haria el messagebox y grabo los errores en un dbf
do errores
ENDTRY

funcionaria como global? cualquier error con problemas como tablas,
indices, bloqueos etc. lo toma?
que es lo que me interesa, dado que con line(1) en un on error nunca obtengo
la linea donde se produce el error.

Gracias

Dario

foxteban

unread,
Apr 1, 2012, 4:32:32 PM4/1/12
to Comunidad de Visual Foxpro en Español
Victor

Gracias por tu aporte, excelente, voy a tomar en cuenta tus
sugerencias.
Ahora mi pregunta con respecto al TRY - CATCH, es si hay que manejarlo
como un IF-ENDIF, es decir que la rutina quede dentro del TRY -
CATCH ?.
Entonces esta buena la Pregunta del Gaucho si es posible ponerla al
principio de la ejecucion del programa para ver si abarca todo el
sistema, si no habria que incorporarlo por cada formulario. OK?
Bueno gracias por todo
Un saludo
Esteban

Carlos Miguel FARIAS

unread,
Apr 1, 2012, 5:40:45 PM4/1/12
to publice...@googlegroups.com
VFP cuenta con tres formas de gestionar errores:
ON ERROR, que viene ya desde el viejo fox para dos.
Metodo ERROR, que se puede poner en cualquier clase, no solo en formulario
TRY CATCH, que permite "envolver" un trozo de código y si en el tramo de código entre el TRY al primer CATCH se produce un error, el control pasa al CATCH que maneje ese error o al que se indique generico si no hay uno específico.
No hay uno mejor otro, pero los tres juntos te permiten tener un control de errores superior que utilizar uno solo.
ON ERROR te ataja al final, cualquier error que no capturaron los metodos anteriores, es más, si queres irte desde cualquiera de los otros errores al ON ERROR, usas un comando ERROR (que funciona como el THROW que se usa con TRY CATCH).
El método Error en las clases, permite generalizar el tratamiento de errores comunes en las instancias de los distintas clases. Eso reduce la codificación aprovechando la herencia y unifico el sistema de mensajes de error y recuperación (si factible) por parte del usuario o del programa. Este metodo que existe por si mismo (como el INIT) recibe como parámetros, codigo error, metodo y número de línea.
El TRY CATCH es una capa más, que me permite "proteger" al programa de fallas muy particulares en puntos particulares del código. Aunque podría envolver todo con un TRY CATCH y asi a todos los niveles, el TRY CATCH no puedo heredarlo por si mismo (por supuesto que si es código de una clase base, si) y debo escribirlo en cada lugar (multiples capas de "envoltura").
Creo que la suma de los tres, cada cual usado apropiadamente, puede lograr un esquema de control de errores mucho más compacto que usandolos por separado.
PHP por ejemplo, solo tiene el equivalente al ON ERROR, tiene un genérico para excepciones lanzadas no atajadas (THROW fuera de un entorno try catch) y el TRY CATCH.
VFP: 3, PHP 2.
Saludos: Miguel, La Pampa (RA)


El 1 de abril de 2012 18:03, Victor Espina <vesp...@gmail.com> escribió:
Como indico en el post, la idea es tener tres niveles de manejo de error:

- Local, que equivaldria a usar TRY-CATCH para procesos donde sabemos que pueden ocurrir problemas
- Formulario, que manejaria cualquier error inesperado ocurrido dentro de un formulario, permitiendo que se cierre el formulario sin problemas sin afectar el resto de la aplicacion
- Aplicacion, que manejaria cualquier error ocurrido fuera de un formulario y llevaria a la finalizacion inmediata de la aplicacion.

El nivel mas general, el de la aplicacion, normalmente se implementa como un TRY-CATCH que engloba al formulario principal y/o el READ EVENTS.

Saludos

Victor Espina

Walter R. Ojeda Valiente

unread,
Apr 2, 2012, 8:24:43 AM4/2/12
to publice...@googlegroups.com
Muy bien explicado Víctor.

Algo bastante similar es lo que hago yo.

Saludos.

Walter.





Date: Sun, 1 Apr 2012 07:52:28 -0700
From: vesp...@gmail.com
To: publice...@googlegroups.com
Subject: [vfp] Re: Como utilizar rutinas de error en los formularios

Victor Espina

unread,
Apr 1, 2012, 5:03:00 PM4/1/12
to publice...@googlegroups.com
Como indico en el post, la idea es tener tres niveles de manejo de error:

- Local, que equivaldria a usar TRY-CATCH para procesos donde sabemos que pueden ocurrir problemas
- Formulario, que manejaria cualquier error inesperado ocurrido dentro de un formulario, permitiendo que se cierre el formulario sin problemas sin afectar el resto de la aplicacion
- Aplicacion, que manejaria cualquier error ocurrido fuera de un formulario y llevaria a la finalizacion inmediata de la aplicacion.

El nivel mas general, el de la aplicacion, normalmente se implementa como un TRY-CATCH que engloba al formulario principal y/o el READ EVENTS.

Saludos

Victor Espina

On Sunday, April 1, 2012 3:32:32 PM UTC-5, foxteban wrote:
Reply all
Reply to author
Forward
0 new messages