Finalizar la aplicacion actual mediante un Abend (VFP)

From codeWiki
Jump to: navigation, search

Por: VictorEspina

Cualquiera que haya trabajado con VFP por algún tiempo sabe lo difícil que puede llegar a ser lograr que la aplicación finalize en un punto dado luego de un error inesperado. En teoria la cosa debería ser tan simple cono ejecutar un CLEAR EVENTS y luego poner el código de limpieza después del READ EVENTS, pero muchas veces me ha sucedido que al intentar hacer cosas como CLEAR ALL o CLOSE ALL se producen errores extranos que pueden terminar en una aplicación que no termina de finalizar del todo.


Una forma salomonica de evitar este problema es ejecutar un Abend o "finalización anormal" de nuestro programa, mediante la terminación forzada del proceso asociado a la aplicación. Esto tiene la ventaja de que podemos estar seguros que la aplicación terminara sin importar cual sea su estado actual. Usando las ventajas del TRY - CATCH podemos lograr cerrar los archivos de datos y conexiones de forma segura antes de mandar a finalizar el proceso, todo lo cual nos brinda una forma segura y eficiente de mandar a finalizar nuestra aplicación en cualquier momento.


Aca les dejo una implementación del Abend para VFP usando llamadas API para determinar el processID asociado a nuestra aplicación y terminarlo.


* Abend
* Ejecutar una salida no programada (Abnormal End) de la aplicacion actual. Al invocarse
* esta funcion la aplicacion actual finalizara inmediatamente.
*
* Perform an Abnormal End of the current application. When this function is called the
* current application will be terminated immediately.
*
PROCEDURE Abend
 *
 TRY
  * API Declaration
  DECLARE INTEGER GetWindowThreadProcessId IN user32 ;
         INTEGER hWnd, INTEGER@ nProcID 
  DECLARE INTEGER GetActiveWindow IN user32                  
  DECLARE INTEGER OpenProcess IN kernel32 ;
         INTEGER dwDesiredAccess, INTEGER blnheritHandle, INTEGER dwAppProcessId
  DECLARE INTEGER TerminateProcess IN kernel32 ;
         INTEGER nPID, INTEGER exitcode
  DECLARE INTEGER CloseHandle IN kernel32 ;
         INTEGER hObject
         
  * Get current app's HWnd 
  LOCAL nHWnd
  IF "06." $ VERSION()
   nHWnd=GetActiveWindow()
  ELSE
   nHWnd=_SCREEN.hWnd
  ENDIF
  
  * Get app's process ID
  LOCAL nProcId
  nProcID=0
  GetWindowThreadProcessId(nHWnd, @nProcID)
  
  * Close all open tables, cursors and ODBC connections
  CLOSE DATABASE ALL
  SQLDISCONNECT(0)
    
  * Kill app's process
  LOCAL nHProc
  STORE 0 TO nHProc
  nHProc=OpenProcess(1, 0, nProcID)
  IF nHProc > 0
   TerminateProcess(nHProc,0)
   CloseHandle(nHProc)
  ENDIF 
  
 CATCH TO ex
  * Optionally show an error message

 ENDTRY 
 *    
ENDPROC
 
Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox