lunes, 6 de abril de 2009

Actualización automática de aplicaciones

En la entrada anterior publique un sistema para realizar actualizaciones de nuestras aplicaciones via FTP. Hoy seguiremos hablando del tema, y le daremos otra vuelta de tuerca.

Para actualizar nuestra aplicación usábamos un pequeño programa “ActVer”, que se encargaba de renombrar y lanzar la ejecución de nuestra aplicación.

Al realizar este programa en [x]Harbour, nos queda de un tamaño bastante considerable teniendo en cuenta lo poco que hace, eso es debido a que como poco cualquier ejecutable Harbour se lleva dentro la maquina virtual.
Para mejorar el tamaño crearemos una versión de ActVer, pero escrita en C, con lo que pasaremos de los 1,46 MB de la versión de harbour a los 16 KB de la versión compilada en C (1,519,616 bytes menos).

Ademas para no tener que distribuir dos ejecutables, embeberemos ActVer.exe dentro de nuestra aplicación, concretamente en el fichero de recursos, y lo extraeremos solo en el momento que sea necesario actualizar nuestra aplicación.

El codigo de ActVer.C queda de la siguiente manera.

#include "stdio.h"
#include "windows.h"

int main( int argc, char *argv[])
{
Sleep(700);
DeleteFile( argv[1]);
rename( "tmp.exe",argv[1]);
WinExec(argv[1],1);
return EXIT_SUCCESS;
}


Ahora vamos a insertarlo dentro de nuestra aplicación, para ello añadimos la siguiente linea en nuestro fichero de recursos, xxxxx.RC

ACTVER RCDATA "ActVer.exe"

RCDATA nos permite insertar directamente datos binarios en nuestro ejecutable (graficos, otros exe, …)

Con esta linea, la siguiente vez que compilemos nuestra aplicación, actver quedara incrustado dentro de nuestro programa, ahora solo nos hace falta el poder extraerlo, cosa que haremos con el siguiente código (también en c).

Insertamos el código de la función en c, en nuestro fuente prg Harbour.

#pragma BEGINDUMP
#include "Windows.h"
#include "hbApi.h"
HB_FUNC( RESTOFILE )
{
HRSRC res=FindResource(NULL,"ACTVER",RT_RCDATA);
LPDWORD bytesWritten;
int size=SizeofResource(NULL,res);
HGLOBAL hRes=LoadResource(NULL,res);
unsigned char *pRes=(unsigned char *)LockResource(hRes);
HANDLE hFile=CreateFile("ACTVER.EXE",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
WriteFile(hFile,pRes,size,&bytesWritten,NULL);
CloseHandle(hFile);
}
#pragma ENDDUMP


Y con esto ya veis que es muy sencillo el incorporar ficheros binarios en nuestro EXE, esta es una posible utilidad, pero seguro que le encontrareis alguna otra.

Para que el PRG de nuestro anterior hilo incorpore esta funcionalidad, debemos añadir el codigo antes citado, y realizar una llamada a la función ResToFile() en la linea anterior a WinExec.

UpdFtp2.prg
ActVer.c
UpdFtp2.zip contiene UpdFtp2.exe
ActVer.rc
ActVer.Exe

2 comentarios:

RenOmaS dijo...

Aunque no lo he probado aun, una idea sencillamente genial
Nunca me ha gustado la idea de tener otro exe en el directorio para hacer el proceso de upgrade.

Felicitaciones

TecniSoftware dijo...

Gabriel:

Muchas gracias por el aporte!
Lo he implementado y me funciona perfectamente pero queria pedirte ayuda por que no tengo mucho manejo de c.
El tema es asi:
En actver.c necesito poder enviarle un parametro ademas del nombre del fichero, para poder hacer el WinExec con argv[1]
Necesito poder hacer algo asi: WinExec( argv[1] + " /SERVER", 1 ) o lo equivalente ( se que esto no funciona )
Muchas gracias!!!