Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Actualizar .exe (https://www.clubdelphi.com/foros/showthread.php?t=37444)

julian_ch 14-11-2006 00:46:54

Actualizar .exe
 
Hola!! Estoy haciendo un programa y se ejecuta en varios equipos, lo que quiero es que cuando cambie el .exe del servidor se actualicen automaticamente los .exe clientes, para esto he pensado en que junto a cada .exe haya un ficherito que ponga la version y si detecta que la version del servidor es mas nueva que la del cliente se actualice, ahora viene lo bueno, como puedo yo desde mi propio .exe copiar el otro y machacarlo?? Al estar ejecutandose me daria un error, a alguien se le ocurre alguna idea, muchas gracias!!!!!

seoane 14-11-2006 01:00:24

Cita:

Empezado por julian_ch
... como puedo yo desde mi propio .exe copiar el otro y machacarlo?? ...

La respuesta corta es que no puedes. No puedes modificar un ejecutable mientras estas en ejecución, así que necesitas la ayuda de alguien. Esa ayuda puede ser un programa auxiliar, un archivo .bat, o si no te importa esperar, puedes programar el reemplazo en el siguiente reinicio del equipo. A mi no se me ocurren mas ideas ...

dec 14-11-2006 01:01:47

Hola,

No puedes "machachar" el ejecutable mientras este esté en ejecución. Lo que se suele hacer es interponer un programa (aparte) que sea el encargado de descargar una versión actualizada de tu programa, y, cuando tu programa se cierre, sea este programa intermedio el que se encarge de borrar el antiguo ejecutable y sustituirlo por el actualizado.

Evidentemente lo expongo todo muy sintéticamente. Puedes buscar información en estos Foros sobre esta tarea de actualizar programas, puesto que se ha tratado en más de una ocasión de esto y se han dado varias soluciones al respecto.

dec 14-11-2006 01:02:45

Hola,

Eco, eeeeeeecoooo... :)

julian_ch 14-11-2006 01:06:30

Ok, gracias por responder tan pronto, voy a ponerme a buscar..........

Salu2!!!

julian_ch 14-11-2006 01:46:13

Cita:

Empezado por dec
Puedes buscar información en estos Foros sobre esta tarea de actualizar programas, puesto que se ha tratado en más de una ocasión de esto y se han dado varias soluciones al respecto.

He encontrado este hilo en el foro http://www.clubdelphi.com/foros/showthread.php?t=32550 , pero no consigo hacerlo funcionar sin servidor ftp o http, no hay nada parecido a esto pero que no necesite ningun tipo de servidor, sino un equipo que haga de servidor???


Gracias!!!!

dec 14-11-2006 01:48:37

Hola,

Habría que hablarlo, pero, si un equipo hacer de servidor... ya tenemos servidor. ¿No?

julian_ch 14-11-2006 01:52:17

Si lo miras asi....... jeje pero es servidor de aplicaciones, no es ni web ni ftp

seoane 14-11-2006 02:03:10

Supongo que estamos hablando del programa "agent", si no recuerdo mal, que no lo hago ;) En el código encontraras una función tal que así:

Código Delphi [-]
function Bajar(Url: string; Archivo: string): Boolean;

Esta función baja un archivo de un http o ftp y lo guarda en el disco duro, pues solo tienes que reemplazar esa función por la que necesites para obtener los archivos del "servidor de aplicaciones". No estoy seguro, pero si el programa esta colocado en una carpeta compartida se podría usar la instrucción Copyfile, corregirme si me equivoco, solo tendrías que tener en cuenta a la hora de hacer los archivos de inicio que donde antes era una url ahora seria la dirección del archivo en formato UNC

julian_ch 14-11-2006 02:14:13

Sasto!! de ese programa estamos hablando, mañana lo pruebo y posteo resultados, de todas formas seoane, aprobechando que estas por aqui, jeje, me podrias decir en que parte del programa "agent" configuras esto:

Paso 6: Si no lo consigue, lo retrasa hasta el proximo reinicio del equipo (No hay prisa)
Paso 7: Esperar (15 minutos o lo que se programe)

porque a mi si que me interesaria que cerrara la aplicacion, la actualizara y la volviera a abrir. Gracias!!!

seoane 14-11-2006 02:26:19

Vamos a destripar esta pieza de relojería :D
Código Delphi [-]
// Esta funcion nos indica si sobre un archivo hay alguna operacion pendiente
// de realizarse en el siguiente reinicio
function Pendiente(Archivo: string): Boolean;
var
  Buffer: PChar;
  Size: Integer;
  i: integer;
begin
  Result := FALSE;
  with TRegistry.Create do
  try
    Access := KEY_READ;
    RootKey := HKEY_LOCAL_MACHINE;
    if OpenKey('\SYSTEM\CurrentControlSet\Control\Session Manager', FALSE) then
    begin
      if ValueExists('PendingFileRenameOperations') then
      begin
        Size := GetDataSize('PendingFileRenameOperations');
        if Size > 0 then
        try
          GetMem(Buffer, Size);
          try
            Fillchar(Buffer^, Size, #0);
            ReadBinaryData('PendingFileRenameOperations', Buffer^, Size);
            for i := 0 to Size - 2 do
              if Buffer[i] = #0 then
                Buffer[i] := #13
              else
                Buffer[i] := upcase(Buffer[i]);
            if StrPos(Buffer, PChar(Uppercase(Archivo))) <> nil then
              Result := TRUE;
          finally
            FreeMem(Buffer);
          end;
        except
        end;
      end;
      CloseKey;
    end;
  finally
    Free;
  end;
end;

procedure Reemplazar(Viejo, Nuevo: string);
begin
  // Comprobamos si hay alguna operacion pendiente sobre los archivos
  if Pendiente(Viejo) or Pendiente(Nuevo) then
    Exit;
  // Si no hay archivo nuevo es que lo queremos borrar
  if Nuevo = '' then
  begin
    // Para borrarlo primero tiene que existir
    if FileExists(Viejo) then
      // Lo intentamos borrar por las buenas
      if not DeleteFile(Viejo) then
        // Si no podemos lo dejamos pendiente hasta reiniciar el equipo
        MoveFileEx(PChar(Viejo), nil, MOVEFILE_DELAY_UNTIL_REBOOT or
          MOVEFILE_REPLACE_EXISTING);
  end
  else
  begin
    // Intentamos reemplazar un archivo por otro, por las buenas
    if MoveFileEx(PChar(Nuevo), PChar(Viejo), MOVEFILE_REPLACE_EXISTING) then
    begin
      // Si lo conseguimos y el archivo se llama autorun.exe lo ejecutamos
      if Uppercase(ExtractFileName(Viejo)) = 'AUTORUN.EXE' then
        ShellExecute(0, nil, PChar(Viejo), nil, nil, SW_SHOW);
    end
    else
    begin
      // Si no conseguimos hacerlo por las buenas lo retrasamos hasta el siguiente reinicio
      MoveFileEx(PChar(Nuevo), PChar(Viejo), MOVEFILE_DELAY_UNTIL_REBOOT or
        MOVEFILE_REPLACE_EXISTING)
    end;
  end;
end;

En ningún momento intento cerrar la aplicación. Si es eso lo que quieres puedes intentar mostrar un aviso y esperar a que el usuario la cierre, cerrarla por las malas o si estas intentando actualizar tu propia aplicación hacer algo como esto (que ya puse en otro hilo):
Código Delphi [-]
procedure Actualizate(Nuevo: string);
var
  Actual: String;
  Buffer: array[0..MAX_PATH] of Char;
begin
  if GetShortPathName(PChar(ParamStr(0)),@Buffer, Sizeof(Buffer) -1) = 0 then
    Exit;
  Actual:= String(PChar(@Buffer));
  if GetShortPathName(PChar(Nuevo),@Buffer, Sizeof(Buffer) -1) = 0 then
    Exit;
  Nuevo:= String(PChar(@Buffer));
  with TStringList.Create do
  try
    Add(':BUCLE');
    Add('Del ' + Actual);
    Add('if %ERRORLEVEL% NEQ 0 goto BUCLE');
    Add('Copy ' + Nuevo + ' ' + Actual);
    Add('Start ' + Actual);
    SaveToFile(ChangeFileExt(ParamStr(0),'.bat'));    
    ShellExecute(0,nil,PChar(ChangeFileExt(ParamStr(0),'.bat')),nil,nil,SW_SHOW);
  finally
    Free;
  end;
end;

// Ejemplo de uso
Actualizate('c:\Windows\Temp\nuevo.exe');
Halt; // Lo apropiado seria usar close, o algo similar

julian_ch 19-11-2006 23:03:26

Muy bueno el programa, lo he probado y con algunas modificaciones es justo lo k necesitaba, no se si te pasara a ti tb seoane pero solo me funciona bien cuando lo ejecuto desde delphi, si es con el ejecutable no funciona, de todas formas gracias!!!!

seoane 19-11-2006 23:09:42

Cita:

Empezado por julian_ch
Muy bueno el programa, lo he probado y con algunas modificaciones es justo lo k necesitaba, no se si te pasara a ti tb seoane pero solo me funciona bien cuando lo ejecuto desde delphi, si es con el ejecutable no funciona, de todas formas gracias!!!!

:confused: ¿que es lo que no te funciona? A mi todos mis programas me funcionan dentro y fuera del IDE.

julian_ch 19-11-2006 23:16:45

Le doy al agent.exe y no hace nada, es como si kedara bloqueado, tengo que ir al administrador de tareas de windows y terminarlo a lo bruto.

seoane 19-11-2006 23:28:52

Ese es el comportamiento normal. El programa esta pensado para que busque actualizaciones cada 15 minutos, en un bucle que nunca termina. Si no es ese el comportamiento que buscas, elimina el bucle y punto, entonces se ejecutara y terminara.

Es decir, donde tienes esto:
Código Delphi [-]
procedure Loop;
var
  Mutex: Cardinal;
begin
  Mutex:= CreateMutex(nil,TRUE,'{C1DEF361-AA1F-4F8F-A35E-29FA672A7E7A}');
  if  GetLastError = 0 then
  begin
    Environment:= TEnvironment.Create;
    try
      StartHook;
      Terminar:= FALSE;
      Espera:= StrToIntDef(ParamStr(1),900000);
      repeat // <--Elimina esto
        Sleep(Espera); // <--Elimina esto
        Vamos;
      until Terminar or (Espera < 5000); // <--Elimina esto
    finally
      StopHook;
      Environment.Free;
    end;
    CloseHandle(Mutex);
  end;
end;

Y puede que tengas que hacer algún ajuste mas. Dentro del IDE te funcionaba porque en los parámetros de ejecución esta puesto 0, es decir le indico un tiempo de espera 0 lo que equivale a que no queremos el bucle.

;) Hay que revisar el código antes de decir que algo no funciona.

julian_ch 19-11-2006 23:32:50

Gracias, tienes razon, revisandolo me acabo de dar cuenta, jeje, ya "funciona" como yo quiero :D


La franja horaria es GMT +2. Ahora son las 01:26:48.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi