El tratamiento de excepciones en el código es cada día más habitual; por una parte debe incluirse en las partes mas "delicadas" del fuente y también el uso de componentes OLE, con comportamientos imprevisibles, debe llevar aparejado la protección contra operaciones de "riesgo".
Clipper incluía BEGIN SEQUENCE. [x]Harboures incluyen tb. el comando TRY (Harbour en modo compatibilidad), y al menos Harbour un BEGIN SEQUENCE un poco más cómodo que en Clipper. A pesar de las mejoras en los xHrbs hay algunas cosas que se pueden hacer para automatizar (y por tanto asegurar) nuestro trabajo.
- Code: Select all Expand view
///////////////////////////
// xTry.Ch
//
//
////////////////////////////////////////
#xCommand xTRY INI TO <oTry> => ;
;
<oTry>:= TxTry():New();;
BEGIN SEQUENCE
#xCommand xTRY END => ;
;
END ;;
oTry:End()
// xTRY CATCH para xTRY INI y xTRY END
// Este en general no sera necesario utilizarlo pq
// normalmente se preguntara y se hara las acciones
// oportunas despues del TRY END
#xCommand xTRY CATCH => ;
;
RECOVER
#xCommand xTRY RETRY INI TO <oTry> ;
[MSGRETRY <cMsgRetry>] => ;
;
DO WHILE .T. ;;
;
<oTry>:= TxTry():New();;
<oTry>:cMsgRetry:= If(<.cMsgRetry.>, <cMsgRetry>, <oTry>:cMsgRetry);;
BEGIN SEQUENCE
#xCommand xTRY RETRY END => ;
;
xTRY END ;;
IF oTry:lError() ;;
IF oTry:lRetry() ;;
LOOP ;;
END ;;
END ;;
EXIT ;;
ENDDO
//eof\\
- Code: Select all Expand view
////////////////////////////////////////
// xTry.Prg eXtended Try
//
//
//
// NOTA:
// ===========================================================
// NO UTILIZAR esta clase y utilizar mejor los comandos
// que hay en xTry.Ch (ver ejemplos)
//
//////////////////////////////////////////////////////////////
*
*
*
*
*
//-------------------------------------------------------------------------//
CLASS TxTry
METHOD New()
METHOD End()
METHOD MsgError() // Mensaje de error 'duro'
METHOD MsgErrorUsuario() // Mensaje error 'blando' para que lo vea el usuario;
// utilizado para operaciones que son mas bien de control de operacion, mas que de error inesperado
METHOD SaveError() // Graba error 'duro'
METHOD lError() INLINE (::oError != NIL)
METHOD lRetry()
METHOD ElaboraError HIDDEN
DATA oError HIDDEN
DATA bError HIDDEN
DATA cMsgRetry
ENDCLASS
*
*
//-------------------------------------------------------------------------//
METHOD New() CLASS TxTry
::bError:= ErrorBlock( { |x| ::oError:= x, Break(x) } )
RETURN Self
*
*
//-------------------------------------------------------------------------//
METHOD End() CLASS TxTry
// Ojo ! *NO* inicializar aqui sobre todo el oError pq
// se puede utilizar, al menos para ::lError(), despues del ::End(); ver
// ejemplos
ErrorBlock(::bError )
RETURN NIL
*
*
//-------------------------------------------------------------------------//
#Define PARAMETROS_DE_USUARIO ;
x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17
METHOD MsgError(PARAMETROS_DE_USUARIO) CLASS TxTry
Local nCount:= PCount()
::ElaboraError(1, nCount, PARAMETROS_DE_USUARIO)
RETURN NIL
*
//-------------------------------------------------------------------------//
METHOD SaveError(PARAMETROS_DE_USUARIO) CLASS TxTry
Local nCount:= PCount()
::ElaboraError(2, nCount, PARAMETROS_DE_USUARIO)
RETURN NIL
*
//-------------------------------------------------------------------------//
METHOD ElaboraError(nQue, nCount, PARAMETROS_DE_USUARIO) CLASS TxTry
Local aPar:= aSize({PARAMETROS_DE_USUARIO}, nCount)
Local oError:= ::oError
*
#Define MSG_ERROR "Se produjo un error controlado !!"
#Define PAR_BASE ;
oError,;
oError:SubSystem(),;
oError:Description,;
oError:Operation,;
oError:SubCode,;
oError:FileName,;
oError:Args,;
oError:OsCode,;
oError:GenCode,;
oError:Severity,;
;
DosError(),;
FError()
IF nQue == 1
IF nCount == 0
msginfo(MSG_ERROR, PAR_BASE)
ELSE
msginfo(MSG_ERROR, PAR_BASE, aPar, aDebug(aPar))
ENDIF
ELSE
IF nCount == 0
GrabaError(MSG_ERROR, PAR_BASE)
ELSE
GrabaError(MSG_ERROR, PAR_BASE, aPar, aDebug(aPar))
ENDIF
ENDIF
RETURN NIL
*
*
*
//-------------------------------------------------------------------------//
METHOD lRetry(cMsgRetry)
Local lRetry
*
IF cMsgRetry == NIL
cMsgRetry:= ::cMsgRetry
ENDIF
IF cMsgRetry == NIL
cMsgRetry:= "Se ha producido un error !!"
ENDIF
*
lRetry:= mMsgYesNo(cMsgRetry+ CRLF+"¿ Reintentar ?")
*
RETURN lRetry
*
*
//-------------------------------------------------------------------------//
METHOD MsgErrorUsuario(cMsgErrorUsuario)
Local lRetry
*
IF cMsgErrorUsuario == NIL
cMsgErrorUsuario:= "No se ha podido realizar la operacion !!"
ENDIF
*
lRetry:= mMsgInfo(cMsgErrorUsuario)
*
RETURN lRetry
*
//eof\\
- Code: Select all Expand view
/////////////////////////////////////////////////////////////////
FUNCTION TestxTry()
#include "xtry.ch"
Local oTry
ALERTA("----Ejemplo 1: Operacion que SI produce un error----")
xTRY INI TO oTry
x:= y // Esto provocara un error
xTRY END
IF oTry:lError()
oTry:MsgError()
ENDIF
ALERTA("----Ejemplo 2: Operacion que NO produce un error----")
xTRY INI TO oTry
x:= 1
xTRY END
IF oTry:lError()
oTry:MsgError()
ENDIF
ALERTA("----Ejemplo 3: Operacion que SI da error, pero posibilidad reintento---")
xTRY RETRY INI TO oTry
x:= y // Esto provocara un error
xTRY RETRY END
IF oTry:lError()
oTry:MsgError()
ENDIF
ALERTA("----Ejemplo 4: Operacion copiado de fichero que SI produce un error----")
xTRY RETRY INI TO oTry
COPY FILE (cOri) TO (cDes)
xTRY RETRY END
IF oTry:lError()
oTry:SaveError()
oTry:MsgErrorUsuario("Fichero no pudo ser copiado !")
ENDIF
ALERTA("----Ejemplo 5: Retry a 'pelo'----")
DO WHILE .T.
xTRY INI TO oTry
x:= y // Esto provocara un error
xTRY END
IF oTry:lError()
IF oTry:lRetry()
LOOP
ENDIF
ENDIF
EXIT
ENDDO
Alerta("-----------------Fin tests xTry----------------")
RETURN NIL
//eof\\
Saludos