Page 1 of 1

Abandonar la aplicacion y correr otra

Posted: 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

Posted: 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.

Posted: 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

Posted: 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

Posted: 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

Posted: 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.

Posted: 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.

Posted: 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")

Posted: 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

_____________________________________________________________ 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

#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

//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

Posted: 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

Posted: 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