Club Builder - Foros de discusión Club Builder
Foro de C++Builder en español
 
 FAQFAQ   BuscarBuscar   MiembrosMiembros   Grupos de UsuariosGrupos de Usuarios   RegistrarseRegistrarse 
 PerfilPerfil   Entra para ver tus mensajes privadosEntra para ver tus mensajes privados   EntrarEntrar 

Actualizar aplicación

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Tips & Tricks
Ver tema anterior :: Ver tema siguiente  
Autor Mensaje
Mensaje    Asunto: Actualizar aplicación Responder citando

Bueno, después de pegarme con el 2007 y dominarlo (que iluso soy), voy a pasaros una aplicación que me ha funcionado medio bien para actualizar automáticamente nuestras aplicaciones.
La cosa empieza desde nuestra aplicación, buscando si hay una actualización pendiente. Yo lo he hecho poniendo el numero de versión por nombre, 1.5.5.5.exe sería MyPrograma.exe versión 1.5.5.5
Os pongo todo el código necesario. Empecemos por MyPrograma.exe y la búsqueda de la actualización en nuestro ftp:
Código:
TStringList *lista = new TStringList;
AnsiString version;
try{
ftp->Connect();
if(ftp->Connected()){
   try{
      ftp->List(lista,"*.exe",false);
      }
   catch(...){
      // archivo no encontrado
      }
   }
   ftp->Quit();
}
catch(...){
      // no hay conexion
      }

// verificar nueva versión
if(lista->Count){
   GetVersionInfo(version); // averiguar nuestra version
   version=version+".exe";
   if(lista->Strings[0]>version){
        WinExec("actualizador",SW_SHOW); // se le supone en el mismo directorio
        Application->Terminate(); // terminar MyPrograma.exe
      }
   }


La función de "capturar" la versión actual (declararlo en el h):
Código:
void GetVersionInfo(AnsiString &pVersion)
{
char MyFileName[100]={"MyPrograma.exe"};

struct  TFixedFileInfo
{
    int Signature;
    int StructVersion;
    short MinorVersion;
    short MajorVersion;
    short Build;
    short Release;
};

    unsigned long Tmp, VersionInfoSize;
    VersionInfoSize = GetFileVersionInfoSize( (LPTSTR) MyFileName,&Tmp);
    if (VersionInfoSize)
    {
        TFixedFileInfo *MyFileInfo;
        char *MyBuf = new char[VersionInfoSize];
        GetFileVersionInfo(MyFileName, 0, VersionInfoSize, MyBuf);
        unsigned int ii = sizeof(MyFileInfo);
        VerQueryValue(MyBuf, "\\", (void **) &MyFileInfo, &ii);
        AnsiString MyString = MyFileInfo->MajorVersion;
        AnsiString TmpString = MyString + ".";
        MyString = MyFileInfo->MinorVersion;
      TmpString += MyString + ".";
      MyString = MyFileInfo->Release;
      TmpString += MyString + ".";
      MyString = MyFileInfo->Build;
      TmpString += MyString;
      pVersion = TmpString;
      VerBs=IntToStr(MyFileInfo->MajorVersion*10000+MyFileInfo->MinorVersion*1000+
      MyFileInfo->Release*100+MyFileInfo->Build);
      delete [] MyBuf;
   } // end if
}  // end GetVersionInfo

Como podréis ver las funciones para ver si hay actualización es simple. Ahora pasaremos a ejecutar (y ver) el actualizador. Haremos un Form con un TIdFTP, un StaticText y una ProgressBar y este es el código para el cpp. No hay nada modificado en los componentes excepto el nombre del ftp, el user y la password.
Código:
//---------------------------------------------------------------------------

#include <vcl>
#pragma hdrstop

#include "actuali.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "IdExplicitTLSClientServerBase"
#pragma resource "*.dfm"
TForm1 *Form1;
AnsiString nuevo,directorio;
long dlsize;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
// directorio de trabajo
directorio=ExtractFilePath(Application->ExeName);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdFTP1Work(TObject *ASender, TWorkMode AWorkMode,
     int AWorkCount)
{
ProgressBar1->Position=AWorkCount;
StaticText1->Update();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdFTP1WorkBegin(TObject *ASender, TWorkMode AWorkMode,
     int AWorkCountMax)
{
if (AWorkCountMax > 0)   ProgressBar1->Max=AWorkCountMax;
else ProgressBar1->Max=dlsize;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdFTP1WorkEnd(TObject *ASender, TWorkMode AWorkMode)
{
AnsiString flocal=directorio+"MyPrograma.exe";
// Actualizado -> parar programa
StaticText1->Caption="Se ha instalado la nueva versión "+nuevo;
Idglobal::Sleep(2000); // unos segundos para leer
WinExec(flocal.c_str(),SW_SHOW);   // ejecutar la aplicación
Application->Terminate(); // terminar con el actualizador
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
AnsiString Valor;
TStringList *lista = new TStringList; // lista de archivos
AnsiString flocal=directorio+"MyPrograma.exe"; // nombre de la aplicacion
StaticText1->Update();
try{
IdFTP1->Connect();
if(IdFTP1->Connected()){
   try{
      // el archivo de actualizacion ya existe segun MyPrograma.exe
      IdFTP1->List(lista,"*.exe",false);  // buscar archivo
      nuevo=lista->Strings[0];

      // el nombre es el numero de version 1.5.5.5 (7.3)
      Valor=nuevo;
      Valor.Delete(nuevo.Length()-3,5); //eliminar .exe
      StaticText1->Caption="Descargando actualización del programa Versión "+Valor;
      StaticText1->Update(); // necesario

      dlsize=IdFTP1->Size(nuevo); // tamaño del archivo
      IdFTP1->Get(nuevo,flocal,true); // descargar archivo
      // nuevo = nombre del archivo en el ftp
      // flocal = fichero local = nombre de MyPrograma.exe
      nuevo=Valor; // pasamos el numero de version a global
      }
   catch(...){
      // archivo no encontrado;
      }
   }
   IdFTP1->Quit();
}
catch(...){
      // no hay conexxion
      }
}


Si hay dudas, ya sabéis que hacer. Si hay mejoras, pues mejor aun
En los comentarios están casi todas las respuestas de porque esto funciona.

Saludos, Bosoft.

PD: Angel, lo he terminado antes de lo esperado.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Una cosa que se podría hacer es en lugar de verificar la versión mediante el sistema de incluir la misma en el nombre es verificar la fecha del fichero con las funciones FileDateToDateTime y FileAge, de forma que si el programa que hay en el servidor es más moderno que el que corre en la máquina, se descarga y listo.

De todas formas, ¡vaya curro que tiene la herramienta! Muy buena.
_________________
Un saludo

Necesitamos tu ayuda: Envía AI al 27595 (Coste 1,20 euros + IVA)
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: Responder citando

Hola Angel:

Angel escribió:
Una cosa que se podría hacer es en lugar de verificar la versión mediante el sistema de incluir la misma en el nombre es verificar la fecha del fichero con las funciones FileDateToDateTime y FileAge, de forma que si el programa que hay en el servidor es más moderno que el que corre en la máquina, se descarga y listo.


No estoy de acuerdo con eso de las fechas. La versión la pones tu, pero la fecha puede variar según la maquina, o el server, con lo cual fallaría algunas veces. Visto lo simple que es comprobar la versión y ponerla en tu aplicación no puede dar a error, aunque para gustos colores. Ya se que tu te mueves como pez en el agua con las fechas, pero yo lo vi muy complicado leer la fecha del archivo en el servidor y peor compararlas.

Gracias por el alago, y si ves algun defecto o mejora, no dudes en comentarlo.

Saludos, Bosoft.
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Hola,

yo lo tengo parecido, pero mas complicado, pues para facilitar las actualizaciones tengo la aplicación fragmentada en bpl (me resulta mas fácil que con dll).

Para dar mas información del archivo a descargar, tengo un ini con el mismo nombre del archivo, donde guardo el tamaño(es lo que uso para saber si se actualiza, si es diferente hay que actualizar), si está comprimido(para descargar mas rápido),... incluso si es el mismo actualizador, que tambien se tiene que poder actualizar.

Primero descargo los ini, comprueba los tamaños de los diferentes archivos, y si es necesario descarga los archivos y los sustituye.

Un rollo, pero me funciona.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Dirección AIM
Mostrar mensajes de anteriores:   
Cambiar a:  
No puedes publicar temas nuevos en este foro
No puedes responder a temas en este foro
No puedes editar tus mensajes en este foro
No puedes borrar tus mensajes en este foro
No puedes votar en las encuestas de este foro


Hosting WordPress Indedmedia desde 3,99 €
© 2002–2026 Club Builder · Funciona con phpBB.