Descargar y actualizar un EXE

Descargar y actualizar un EXE

Postby cmsoft » Wed Mar 27, 2019 2:48 pm

Estimados:
Tengo un programa que se actualiza, según si la version que tiene el cliente esta o no actualizada, haciendo click en un formulario de actualizacion, que el cliente elije ejecutar.
Para ello, descargo el programa actualizado desde un ftp.
Para ello, utilice una funcion que escribio Biel en su blog (http://bielsys.blogspot.com/2009/04/act ... ca-de.html) hace ya mucho tiempo.
El problema me surge ahora, en algunas maquinas con Windows 10 (no en todas), descarga el programa, pero no renombra el exe descargado por el actual.
Alguien le ha pasado o tiene alguna solucion alrtenativa
Este es mi codigo:
Code: Select all  Expand view  RUN

   cFile := "aplicacion.exe"
   cDirLocal := hb_curdrive()+":\"+CurDir()
   IF ConectaServerFtp()      
       aFiles:=oFtp:ListFiles('public_html/descargas/aplicacion.exe')
       IF LEN(aFiles) = 0
          MsgStop("
Error de descarga al comparar!!","ERROR")
          oFtp:Close()
          RETURN .F.
       ENDIF
       nSize := aFiles[1,2]      
       IF nSize = 0
          MsgStop("
Error de descarga al bajar!!","ERROR")
          oFtp:Close()
          RETURN .F.
       ENDIF  
       oFtp:DownLoadFile( "
.\tmp.exe", 'public_html/descargas/aplicacion.exe' )
       ELSE
       oFtp:Close()
       MsgStop("
Fallo la conexion...","Error")
       RETURN nil
   ENDIF    
   oFtp:Close()
   IF FSIZE("
.\tmp.exe") = nSize .AND. nSize > 0
      MsgWait("
Reinciciando la aplicacion","Espere",1)      
      ResToFile()
      WinExec( cDirlocal+'\ActVer.exe '+ cFile ,0)
      PostQuitMessage(0)
      QUIT
      ELSE
      MsgStop("
Error de descarga al renombrar!!","ERROR")
      QUIT
   ENDIF  
RETURN .t.


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

#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
 

El codigo en C de ACTVER.EXE es el siguiente:
Code: Select all  Expand view  RUN

#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],argc);
return EXIT_SUCCESS;
}
 

Gracias de antemano
User avatar
cmsoft
 
Posts: 1293
Joined: Wed Nov 16, 2005 9:14 pm
Location: Mercedes - Bs As. Argentina

Re: Descargar y actualizar un EXE

Postby hmpaquito » Wed Mar 27, 2019 3:05 pm

Alguien le ha pasado o tiene alguna solucion alrtenativa


El mundo del renombramiento de ejecutables es todo una odisea. Lo que antes no renombraba ahora lo hace y al revés.

Mi solucion:

1 - Suponiendo que tu programa se llama aplicacion.exe, al descargar desde el ftp descargalo añadiendole un sufijo unico, por ejemplo aplicacion_27032019_160200.exe.
2 - Luego, al arrancar el aplicacion.exe, justo al entrar, localiza que ejecutable aplicacion_*.exe es más reciente y lanzalo, cerrando al llamador con un Quit y
3 - al entrar con este ejecutable renombrado intenta:
a) Borrar ejecutables renombrados antiguos
b) COPY FILE aplicacion_27032019_160200.exe TO aplicacion.exe

Con estos dos ultimos pasos se logra mantener como ejecutable aplicacion.exe y la carpeta limpia de renombrados aplicacion_*.exe
hmpaquito
 
Posts: 1482
Joined: Thu Oct 30, 2008 2:37 pm

Re: Descargar y actualizar un EXE

Postby cmsoft » Wed Mar 27, 2019 4:22 pm

Gracias por responder hmpaquito!
De la forma que lo hago, el exe principal es que lanza tanto la descarga y luego lanza a ACTVER.EXE que es el que se encarga de renombrar y volver a lanzar al ejecutable principal.
Cuando lo descargo lo grabo con un nombre que no es único, lo grabo siempre como TEMP.EXE , pero inmediatamente despues el programa ACTVER renombra ese exe como aplicacion.exe (espera 7 segundos) y lanza nuevamente aplicacion.exe. De esta manera el cliente solo ve que el programa se reinicia... Pero no hay un segundo programa Fivewin.
Igualmente por lo que me decis, voy a probar descargarlo con un nombre unico, y en el ACTVER cambiar el borrado por un renombrado del exe original
User avatar
cmsoft
 
Posts: 1293
Joined: Wed Nov 16, 2005 9:14 pm
Location: Mercedes - Bs As. Argentina

Re: Descargar y actualizar un EXE

Postby EBM » Thu Mar 28, 2019 1:06 pm

Hola

Yo lo tengo funcionando de la siguiente manera:

Bajo el nuevo ejecutable de un ftp a una carpeta llamada "Descargas" dentro de la carpeta de mi aplicación, después llamo desde mi aplicación a otro programa que es el que hace la actualización del ejecutable:

Verifico que exista el nuevo ejecutable y si existe, llamo al programa que actualiza:

FUNCTION Actualizar()

If !MsgNoYes( "El sistema se actualizará, está usted seguro de realizar este proceso?","Confirme" )
Return NIL
EndIf

ShellExecute( 0, , "actualiza.exe", , NIL, 3 )

oVentPrin:bValid := { || NIL }

PostQuitMessage( 0 )
Quit

Return NIL


Y este es el código del programita que hace la actualización del ejecutable y lo lanza de nuevo:

FUNCTION Actualiza()

SysWait( .7 )

If !File( ".\Descargas\" + "SICCE.EXE" )
MsgStop( "No se encuentra el archivo para actualizar","Error" )
WinExec( "sicce.exe", 0 )
PostQuitMessage( 0 )
Quit
EndIf

If File( "SICCEOLD.EXE" )
FErase( "SICCEOLD.EXE" )
EndIf

FRename( "SICCE.EXE", "SICCEOLD.EXE" )
MoveFile( ".\Descargas\" + "SICCE.EXE", ".\" + "SICCE.EXE" )

MsgInfo( "Sistema actualizado con éxito","Aviso" )
WinExec( "sicce.exe", 0 )
PostQuitMessage( 0 )
Quit

Return NIL


A mi me funciona sin problemas.

Saludos !

Eduardo Borondón Muñiz
EBM
 
Posts: 147
Joined: Tue Oct 11, 2005 8:22 pm
Location: Guadalajara, Jal Mexico

Re: Descargar y actualizar un EXE

Postby cmsoft » Thu Mar 28, 2019 3:01 pm

Hola Eduardo!
Gracias por tu interés y por tu sugerencias.
Al final hice algo parecido a lo que vos me decis, y a la propuesta de hmpaquito, pero desde dentro del ejecutable ACTVER.EXE que es un programa C que "guardo" dentro del recurso, y lo extraigo para la ocacion.
Asi quedo:
Code: Select all  Expand view  RUN

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

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

Esto funciona mucho mejor, pero igual estoy teniendo un problema, o con los nombres largos de directorios, o con los permisos de Windows 10.
El programa se instala con un instalador de Inno Setup, y el usuario puede elegir la ruta donde instalarlo. Si el cliente tiene Windows 10, generalmente le propone descargarlo en Archivos de programas (x86) y la carpeta que elija (que viene por defecto con el nombre del programa).
Si el nombre de la carpeta es largo y contiene espacios, no hace bien el reemplazo. Si es corto (o si le modifico a mano el nombre de la carpeta por uno corto) el reemplazo lo hace perfecto...
Sigo investigando...
User avatar
cmsoft
 
Posts: 1293
Joined: Wed Nov 16, 2005 9:14 pm
Location: Mercedes - Bs As. Argentina

Re: Descargar y actualizar un EXE

Postby mariordz » Thu Apr 04, 2019 11:13 pm

Les comparto como lo hago yo, este método lo he usado desde hace varios años y nunca me ha dado problemas, independientemente de las versiones de windows en las que se ejecute (funciona desde windows 98 hasta windows 10).

Básicamente necesitas dos ejecutables, un ejecutable que es tu aplicación principal y uno que se encargará de actualizarlo.


En mi código tengo una variable que tiene el número de versión del ejecutable Tubelite.EXE, cuando quiero publicar alguna actualización lo único que hago es cambiar el valor de esta variable y poner el mismo valor en una pequeña DBF que solo tiene un registro, en el que guardo el número de versión y un campo MEMO donde guardo una breve explicación de los cambios o mejoras realizadas, al iniciar mi programa abro ese DBF (puede ser una base de datos de cualquier tipo), la leo y comparo el valor de ese campo contra el valor de mi variable, si estos valores son diferentes le muestro un dialogo al usuario indicando que hay una actualización, no le doy la opción de que aplique o no la misma, solo le informo que se hará la actualización.

Code: Select all  Expand view  RUN
Public cVer_loc := "3.0.0.0"



NOTA: cuando cambio el valor de la variable en mi código debo cambiar también el valor en la base de datos, de otra manera se quedaría atrapado en un loop, ya que el valor en el código y en la base de datos serían siempre diferentes.

Code: Select all  Expand view  RUN

use &dbvers shared
   goto 1
   store version to cUlt_ver
   store whatsnew to cWhats
   if alltrim(cVer_loc)#alltrim(cUlt_ver)
    Public oDialver, oGet1v, oGet2v, oGet3v, oBtn1v
    define dialog oDialver resource "DLGVERSION" of oVentp1 icon "icono1" font oFont1g
    NoCloseButton(oDialver)
    redefine get oGet1v var cVer_loc ID 1 of oDialver READONLY
    redefine get oGet2v var cUlt_ver ID 3 of oDialver  READONLY
    redefine get oGet3v var cWhats ID 5 of oDialver MEMO READONLY
    redefine button oBtn1v ID 6 of oDialver action (nValsal:=1,updatever())
    activate dialog oDialver center
   endif


Entonces llamo a la función "updatever()" que es realmente donde se hace la magia, esta función lo que hace son dos cosas, primero verifica que el ejecutable que hará la actualización exista (en mi caso está en el mismo directorio de la aplicación principal), si el archivo existe lo ejecuta WinExec('sacsupdat.exe") y se "suicida" con las instrucciónes
"PostQuitMessage(0)"
"__Quit()"

Code: Select all  Expand view  RUN
Function updatever()
   if file("sacsupdt.exe")
      WinExec("sacsupdt.exe")
      PostQuitMessage(0)
      __Quit()
   else
      ?"No se encontro el archivo de actualización SACSUPDT.EXE. Verificalo y vuelve a intentar"
      aborta()
   endif
return


Como el archivo principal ya no esta en ejecución (puesto que ya se "mato") el ejecutable "sacsupdat.exe" solo tiene unas instrucciones para copiar el archivo tubelite.exe que esta almacenado en una carpeta compartida y sin restricciones de acceso, una vez que lo ha copiado se "suicida" también ya vuelve a llamar al Ejecutable original

Code: Select all  Expand view  RUN

cFileorig:="\\192.145.1.1\update\tubelite.exe"
cRutaDest := hb_curdrive()+":\"+curdir()+"\"
copy file cFileorig) to (cRutaDest)
WinExec("
tubelite.exe")
      PostQuitMessage(0)
      __Quit()
User avatar
mariordz
 
Posts: 131
Joined: Tue Dec 26, 2006 4:50 pm
Location: Ciudad de México


Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 54 guests