Page 1 of 1

Abandonar la aplicacion y correr otra

PostPosted: Tue Jul 11, 2006 7:04 pm
by RodolfoRBG
Hola amigos,

Intento que de manera automatica se sustituya el EXE que estoy corriendo por uno mas reciente asi que el proceso debe hacer lo siguiente:

Abandonar la presente aplicacion y encadenarse a otra que descomprime un ZIP y que copia el EXE para que sustituya al que originalmente estaba corriendo.

Al momento, en la aplicacion original (Origen.EXE por ejemplo) pongo las siguientes instrucciones:

WINEXEC("Copiar.EXE")
QUIT
M->oWndPrin:End()

donde "Copiar.EXE" se encarga de descomprimir el zip, copiar la nueva version de "Origen.EXE" para que sustituya el "Origen.EXE" viejo y despues abandone "Copiar.EXE" y corra el nuevo "Origen.EXE".

El problema con esas instrucciones es que en efecto se encadena a "Copiar.EXE" pero no siempre abandona "Origen.EXE" y al estar activo no permite sustituirlo por el nuevo.

Alguna idea?

'chas gracias de antemano

PostPosted: Tue Jul 11, 2006 8:55 pm
by Antonio Linares
Rodolfo,

Lo más sencillo es usar un fichero BAT que es el que llama a los ejecutables.

PostPosted: Tue Jul 11, 2006 8:58 pm
by karinha
USE UN ARCHIVO.BAT TIPO:

STATIC lDesligaProg := .F.

LOCAL NOME_ARQ, NREGISTRO

IF lDesligaProg //-> SE .T.

MsgStop( OemToAnsi( "Prezado Usuário: " ) + CRLF + ;
OemToAnsi( "Devido ao Enorme CONSUMO DE RECURSOS do " ) + CRLF + ;
OemToAnsi( "WINDOWS, Necessito Reiniciar o Programa," ) + CRLF + ;
OemToAnsi( "Para Liberação de Memória e Recursos. " ) + CRLF + ;
OemToAnsi( "Desculpe Pelo Transtorno! É Rápido." ) + CRLF + ;
OemToAnsi( "<Click> no Botão <OK> Por Favor... " ), ;
OemToAnsi( "Aviso de Perda de Recursos do Windows. " ) )

oDbfPedf:Close()

// Cria o Arquivo de Lote Balcao.Bat no Diretório, Com as Diretrizes.
IF !FILE( "BALCAO.BAT" )

NOME_ARQ := FCREATE("BALCAO.BAT")

NREGISTRO := "@ECHO OFF" ;
+ CRLF + ;
"CLS" + ;
+ CRLF + CRLF + ;
"BALCAOW.EXE" + ;
+ CRLF + CRLF + ;
"CLS" + ;
+ CRLF + ;
"EXIT"

FWRITE( NOME_ARQ, NREGISTRO )
FCLOSE( NOME_ARQ )

ENDIF

oFont1:End()

lDesligaProg := .F.

EndDialog()
Release All

WinExec( "BALCAO.BAT", 0 )

__QUIT()

ELSE

oDbfPedf:Close()

oFont1:End()

lDesligaProg := .F.

Release All

ENDIF

PostPosted: Wed Jul 12, 2006 1:13 am
by RodolfoRBG
Jovenes,

No puedo usar un archivo de lotes que llame primero al "Origen.EXE" y despues al "Copia.EXE" porque el proceso es muy eventual, no se hace cada vez que se corre "Origen.EXE".

El ejemplo de Joao para crear y correr un archivo BAT no me funciono.

Si no hay alguna instruccion para cerrar "Origen.EXE" y correr "Copia.EXE" existira alguna manera que desde "Copia.EXE" cierre "Origen.EXE"?

'chas gracias por su paciencia

PostPosted: Wed Jul 12, 2006 2:55 am
by wmormar
RodolfoRBG wrote:Jovenes,

No puedo usar un archivo de lotes que llame primero al "Origen.EXE" y despues al "Copia.EXE" porque el proceso es muy eventual, no se hace cada vez que se corre "Origen.EXE".

El ejemplo de Joao para crear y correr un archivo BAT no me funciono.

Si no hay alguna instruccion para cerrar "Origen.EXE" y correr "Copia.EXE" existira alguna manera que desde "Copia.EXE" cierre "Origen.EXE"?

'chas gracias por su paciencia


Podrias probar

SHELLEXECUTE()
oWnd:END()

por ahi va la idea

PostPosted: Wed Jul 12, 2006 7:39 pm
by infosys
Pienso que tu problema se solucionaria, con un programa intermedio que es llamado desde EXIT PROCEDURE....., sobre la aplicacion que vas a reemplazar, yo hago lo mismo y lo solucione de esta manera.

PostPosted: Wed Jul 12, 2006 7:57 pm
by RodolfoRBG
Infosys,

De hecho el programa "Copia.EXE" es un programa intermedio que se corre desde "Origen.EXE", pero este ultimo como que no se termina de cerrar al llamar al primero.

Podrias enviarme o darme un ejemplo de como le hiciste tu?

'chas gracias.

PostPosted: Thu Jul 13, 2006 12:24 am
by R.F.
Rodolfo:

Origen.EXE hace un WinExec("copia.exe") hasta aqui vamos bien. Luego el ORIGEN.EXE tiene que "suicidarse", eso lo haces con un PostQuitMessage(0) y un Quit, quedaria algo asi:

WinExec("copia.exe")
PostQuitMessage(0)
__Quit()

y luego en tu programa COPIA.EXE haces lo que tienes que hacer, y vuelves a lanzar a ORIGEN.EXE

WinExec("origen.exe")

PostPosted: Thu Jul 13, 2006 2:07 pm
by Patricio Avalos Aguirre
Rodolfo:

Esta rutina me ha funciona perfectamente

funciona de la siguiente manera:

1.- Cuando instalo una actualización guardo en la carpeta update\ dos archivo, uno el ejecutable.exe y otro la update.ini, que es el siguiente

Code: Select all  Expand view
_____________________________________________________________ Sistema Administrativo                                    Version 1.0.0
                                    (c) copyright: Patricio Avalos Aguirre, 2005
                                             patricio_avalos_aguirre@hotmail.com
_____________________________________________________________
[Version]
numero=1.0.19
[Revision]
;08 Julio del 2006, versión 1.0.19
;bla bla bla..
;y mas blabla


Code: Select all  Expand view
#Define DRIVELOCAL DiskName() + ":\"+Curdir()

Static oApp

procedure Main()

//mi programa bla bla bla...

return

//-----------------------------------------------------------------------
Init Procedure Inicio()

   oApp := MyApp():Load()
   aEval( DIRECTORY( oApp:cPathTmp + "\*.*" ), { |aFichero| fErase( oApp:cPathTmp + "\"+aFichero[1] ) } )

   if VerUpdate()
      PostQuitMessage( 0 )
      QUIT
   endif

return

//-----------------------------------------------------------------------

CREATE CLASS MyApp

   VAR Usuario          AS CHARACTER   INIT ""
   VAR Nombre             AS CHARACTER   INIT ""
   VAR Grupo             AS CHARACTER   INIT ""
   VAR Depto             AS CHARACTER   INIT ""
   VAR Clave             AS CHARACTER   INIT ""

   VAR cPathTmp         AS CHARACTER   INIT DRIVELOCAL + "\TEMPORAL"
   VAR cPathDbf         AS CHARACTER   INIT DRIVELOCAL + "\DATOS"
   VAR cPathUpd         AS CHARACTER   INIT DRIVELOCAL + "\UPDATE"
   VAR cPathLocal        AS CHARACTER   INIT DRIVELOCAL

   //impresion
   VAR Factura           AS CHARACTER  INIT "LPT1"
   VAR Boleta           AS CHARACTER  INIT "LPT1"
   VAR GDespacho         AS CHARACTER  INIT "LPT1"
   VAR ordenCompra      AS CHARACTER  INIT "LPT1"
   VAR Cotizacion       AS CHARACTER  INIT "LPT1"
   VAR GRecepcion       AS CHARACTER  INIT "LPT1"
   VAR SaliBode         AS CHARACTER  INIT "LPT1"
   VAR ordentrabajo       AS CHARACTER  INIT "LPT1"
   VAR Cajadiaria       AS CHARACTER  INIT "LPT1"
   VAR nCredito          AS CHARACTER  INIT "LPT1"
   VAR Arriendo         AS CHARACTER  INIT "LPT1"
   VAR Finiquito        AS CHARACTER  INIT "LPT1"

   VAR AdsServer     AS NUMERIC        INIT ""
   VAR AdsConnect    AS NUMERIC          INIT ADS_LOCAL_SERVER
   VAR cVersion         AS CHARACTER  INIT "1.0.0"

   METHOD Load()
   METHOD Save()
   METHOD End()    INLINE ::Save()

ENDCLASS
//------------------------------------------------------------------------------------------------
METHOD Load( oDbf ) CLASS MyApp
local oIni

INI oIni FILE (::cPathLocal + "\wInvent.ini")

   GET ::cPathDbf     SECTION "Servidor" ENTRY "Name"          OF oIni DEFAULT ""
   GET ::cPathUpd     SECTION "Servidor" ENTRY "Update"        OF oIni DEFAULT ""

   GET ::Factura      SECTION "Puertos"  ENTRY "Factura"       OF oIni DEFAULT "LPT1"
   GET ::Boleta       SECTION "Puertos"  ENTRY "Boleta"          OF oIni DEFAULT "LPT1"
   GET ::GDespacho    SECTION "Puertos"  ENTRY "GDespacho"       OF oIni DEFAULT "LPT1"
   GET ::OrdenCompra  SECTION "Puertos"  ENTRY "ordencompra"    OF oIni DEFAULT "LPT1"
   GET ::Cotizacion   SECTION "Puertos"  ENTRY "Cotizacion"     OF oIni DEFAULT "LPT1"
   GET ::GRecepcion   SECTION "Puertos"  ENTRY "GRecepcion"     OF oIni DEFAULT "LPT1"
   GET ::SaliBode     SECTION "Puertos"  ENTRY "SaliBode"       OF oIni DEFAULT "LPT1"
   GET ::ordentrabajo SECTION "Puertos"  ENTRY "ordentrabajo"    OF oIni DEFAULT "LPT1"
   GET ::Cajadiaria    SECTION "Puertos"  ENTRY "CajaDiaria"    OF oIni DEFAULT "LPT1"

   GET ::cVersion     SECTION "Version"  ENTRY "Version"       OF oIni DEFAULT "1.0.0"
   GET ::Usuario      SECTION "Usuario"  ENTRY "Usuario"         OF oIni DEFAULT ""
   GET ::Nombre       SECTION "Usuario"  ENTRY "Nombre"         OF oIni DEFAULT ""

   GET ::AdsServer    SECTION "ServerAds"  ENTRY "Servidor"       OF oIni DEFAULT ""
   GET ::AdsConnect   SECTION "ServerAds"  ENTRY "TypeConnect"   OF oIni DEFAULT ADS_LOCAL_SERVER

   ::Factura       := Alltrim( ::Factura    )
   ::Boleta      := Alltrim( ::Boleta    )
   ::GDespacho     := Alltrim( ::GDespacho  )
   ::OrdenCompra := Alltrim( ::OrdenCompra)
   ::Cotizacion  := Alltrim( ::Cotizacion )
   ::GRecepcion  := Alltrim( ::GRecepcion )
   ::SaliBode      := Alltrim( ::SaliBode   )
   ::CajaDiaria  := Alltrim( ::CajaDiaria )

ENDINI

return( Self )
// --------------------------------------------------------------------------------------------
METHOD Save( oDbf ) CLASS MyApp
local oIni

if !empty( ::Usuario )
   INI oIni FILE (::cPathLocal + "\wInvent.ini")
   oIni:Set( "Usuario", "Usuario", ::Usuario )
   oIni:Set( "Usuario", "Nombre", ::Nombre )
   oIni := NIL
endif

return( NIL )
// --------------------------------------------------------------------------------------------
Function ViewUsu()
Return( oApp )
// --------------------------------------------------------------------------------------------
static function VerUpdate()
   local oIniUpdate, oIniLocal, cVersion, cVersion2, lReturn := .f.

   if !file( ViewUsu():cPathUpd + "\Update.exe" ) .or. !file( ViewUsu():cPathUpd + "\Wcta.exe" )
      return( lReturn )
   endif

   INI oIniUpdate FILE ( ViewUsu():cPathUpd + "\update.ini" )
   GET cVersion SECTION "Version" ENTRY "numero" OF oIniUpdate DEFAULT "1.0.0"

   INI oIniLocal FILE (ViewUsu():cPathLocal + "\wInvent.ini")

   GET cVersion2 SECTION "Version" ENTRY "Version" OF oIniLocal DEFAULT "1.0.0"

   if PadR( cVersion2,6 ) <> PadR( cVersion,6 )
      if Parame->( NetRLock() )
         Parame->Version := cVersion
         WinExec( ViewUsu():cPathUpd+"\Update.exe "+cVersion )
         lReturn := .t.
      endif
   endif
   USE

return( lReturn )
//------------------------------------------------------------------------------------------------



Code: Select all  Expand view
//programa update.exe
//este debe compilarse solo...

#include "ini.ch"
#include "FiveWin.ch"
#Define DRIVELOCAL DiskName() + ":\"+Curdir()
//----------------------------------------------------------------------------
function Update( cValor )
local PATHSERVER,   PATHDATOS, lExe, oIni, Usuario

   if empty( cValor )
      return( .f. )
   endif

   INI oIni FILE (DRIVELOCAL + "\wInvent.ini")
      GET Usuario      SECTION "Usuario"  ENTRY "Usuario" OF oIni DEFAULT ""
      GET PATHSERVER   SECTION "Servidor" ENTRY "Update"    OF oIni DEFAULT ""
      GET PATHDATOS    SECTION "Servidor" ENTRY "Name"    OF oIni DEFAULT ""
     ENDINI

   if !file( PATHSERVER + "\wcta.exe" )
      MsgInfo( "Falta un archivo imposible actualizar" +CRLF+;
      PATHSERVER + "\wcta.exe", "Usuario" )
      return( .f. )
   endif

   if file( DRIVELOCAL + "\wcta.ex_" )
      if fErase( DRIVELOCAL + "\wcta.ex_" ) = -1
         MsgInfo( "Favor borrar archivo de respaldo "+DRIVELOCAL + "\wcta.ex_", "Usuario" )
         return( .f. )
      endif
   endif

   MsgInfo( "Actualización Sistema Win-Facturación" + CRLF + "Versión "+cValor )

   if fRename( DRIVELOCAL + "\wcta.exe", DRIVELOCAL + "\wcta.ex_" ) = -1
      Msginfo( "Error al actualizar"+CRLF+"Cierre todos las ventanas del sistema"+CRLF+CRLF+ "si persiste este error reinicie la maquina", "usuario" )
      return( .f. )
   endif

   Usuario := Alltrim( Usuario )

   lExe := .f.

   MsgRun( "Actualizando aplicación..", "Espere..", ;
              { || lExe := CopyFile( PATHSERVER + "\wcta.exe",;
                                      DRIVELOCAL + "\wcta.exe", .f. ) } )

   if lExe //sa ha copiado correctamente

      oIni := TIni():New(  DRIVELOCAL + "\wInvent.Ini" )

      oIni:Set( "Version", "Version", cValor )
      oIni:Set( "Creado", "Programador", "Patricio Avalos Aguirre" )
      oIni:Set( "Creado", "Email", "patricio_avalos_aguirre@hotmail.com" )
      oIni:Set( "Creado", "Copyright(c)", "2005" )

      MsgInfo( "Actualización se ha realizado con éxito" + CRLF + CRLF +;
               "Vuelva a ejecutar el sistema", "Agrotec Ltda." )

      fErase( DRIVELOCAL + "\wcta.ex_" )

   else

      if file( DRIVELOCAL + "\wcta.exe" )
         fErase( DRIVELOCAL + "\wcta.exe" )
      endif

      fRename( DRIVELOCAL + "\wcta.ex_", DRIVELOCAL + "\wcta.exe" ) //volvemos el resplado a su origen

      MsgInfo( "Error Al actualizar!!"+ CRLF + CRLF + "EXE Error" + CRLF + CRLF + ;
               "Comuniquese con Patricio Avalos Aguirre"+CRLF+"Email:patricio_avalos_aguirre@hotmail.com", "Actualización" )

   endif

Return( .t. )
//-----------------------------------------------------------------------------------------------------
//no recuerdo el autor de esta funcion, pero no es mía
static function CopyFile( cORIGEN, cDestino, lBorrar )
   local cBuffer, fIfile, fOfile, nNumRead

   DEFAULT lBorrar := .F.

   #DEFINE BUF_SIZE 1024
   cBuffer := SPACE(BUF_SIZE)

   fIfile := FOPEN(cORIGEN)

   IF FERROR() != 0
      MsgStop("Error no se ha podido abrir el fichero "+ CRLF+ CRLF + cORIGEN )
      return( .f. )
   ENDIF

   fOFile   := LCreat( cDestino,0 )

   IF FERROR() != 0
      MsgStop("Error no se ha podido crear el fichero "+CRLF+cDESTINO)
      FCLOSE(fIFile)
      return( .f. )
   ENDIF

   nNumRead := FREAD(fIfile,@cBuffer,BUF_SIZE)
   DO WHILE nNumRead == BUF_SIZE
      FWRITE(fOfile, cBuffer, BUF_SIZE)
      nNumRead := FREAD(fIFile,@cBuffer,BUF_SIZE)
   ENDDO
   FWRITE(fOfile, cBuffer, nNumRead)
   FCLOSE(fIFile)
   FCLOSE(fOFile)
   IF lBorrar
      FERASE(cORIGEN)
   ENDIF

return( .t. )
//------------------------------------------------------------------------------------------------


Espero que te sirva,

Saludos
Patricio

La Serena, Chile

PostPosted: Thu Jul 13, 2006 6:31 pm
by RodolfoRBG
Patricio: Gracias por tus atenciones, tu proceso es muy similar al que estaba desarrollando y me diste buenos tips.

Maestro Flores: El secreto fue la funcion: PostQuitMessage(0) era lo que realmente necesitaba, eres un genio, no se que haces en otros lados con tus experimentos, tu mision en la vida es quedarte con nosotros.

P.D.: Con todo los tips que me dieron esto ya funciono, pero les paso otro, para que funcione correctamente todo esto es necesario que al inicio del exe al que se llama, se coloque un MSGINFO() pues al parecer requiere hacer una pausa para que se termine de cerrar el EXE de donde fue llamado.

'chas gracias

PostPosted: Fri Jul 14, 2006 6:39 pm
by Maurilio Viana
RodolfoRBG wrote:Patricio: Gracias por tus atenciones, tu proceso es
(...) se coloque un MSGINFO() pues al parecer requiere hacer una pausa para que se termine de cerrar el EXE de donde fue llamado.


Rodolfo se no quieres nadie visual en inicio del EXE llamado cambia msginfo a SysWait( nSeconds ).

Saludos
Maurilio