2009-06-17 14 views
6

Estoy usando Microsoft Visual Studio 2008 con una implementación de destino de Windows. ¿Cómo puedo hacer que un archivo se actualice solo? Ya tengo la parte "transmitiendo a través de una red", pero ¿cómo puedo hacer que un ejecutable se escriba sobre sí mismo?Cómo puedo hacer una actualización automática de archivos (C++ nativo)

Básicamente, deseo escribir un auto-actualizador para un directorio que también incluya el auto-actualizador, y el actualizador necesita actualizar TODO en el directorio.

Quizás una forma de guardar los cambios en el archivo hasta que se libere el bloqueo de archivos funcionaría. Sin embargo, si tuviera que hacer eso, probablemente lo seguiría con un parche caliente.

+0

Dupe posible: http://stackoverflow.com/questions/250175/writing-my-own-auto-updater – crashmstr

+1

No es una víctima, esto es específicamente NATIVO C++. –

Respuesta

5

Escriba un nuevo ejecutable y elimine o guarde una copia de la anterior; podría enviar un diff a través de la red y tener un tercer programa, el monitor de actualización o lo que sea, para aplicarlo. Sería solo un pequeño script que podría iniciarse desde la aplicación remota cuando se dé cuenta de que hay una actualización disponible. El actualizador podría renombrarse a $ UPDATER_OLD_VERSION o lo que sea, escribir una copia actualizada de sí mismo con el nombre apropiado y luego, cuando se ejecute el nuevo actualizador, verifique si hay un archivo llamado $ UPDATER_OLD_VERSION en el directorio de la aplicación y elimínelo. Todos los otros archivos podrían simplemente actualizarse/sobrescribirse.

+0

No.Esa solución es demasiado desordenada para mí. Prefiero no tener "datos temporales" flotando. ¿Qué pasa si la computadora se bloquea en el medio? –

+3

@wowus: es mucho mejor que se cuelgue la escritura de datos temporales que sobrescribir el exe real. Además, la solución es fácil: escriba en un archivo temporal y luego llame a MoveFile para ponerlo en su ubicación final. En el mismo volumen, MoveFile es atómico, por lo que un bloqueo no lo dejará en un estado incoherente. – Michael

+0

La sugerencia de SoloBold es cómo se hace generalmente este tipo de cosas. La aplicación que está actualizando no puede actualizarse. Como dices, ¿qué pasa si la computadora falla en el medio? –

2

Lo hago usando un InnoSetup setup.exe que se inicia silenciosamente y apaga mi aplicación antes de que comience a instalar los archivos nuevos. Tuve que agregar secciones de Pascal [Código] personalizadas para asegurarme de que todo se apaga, pero hace el trabajo.

+0

A falta de escribir un controlador de dispositivo o piratear el sistema operativo, creo que algún esquema como este es la única forma de hacerlo. Cuando ejecuta un archivo ejecutable en Windows, el sistema operativo lo mantiene abierto y bloqueado. –

3

Generalmente no puede modificar una aplicación mientras se está ejecutando. Usted deberá cerrar el programa original y modificarlo desde otra ubicación.

2

No puede sobrescribir un archivo mientras se está ejecutando, pero PUEDE cambiarle el nombre. En mi actualizador, cambio el nombre del exe existente a algo significativo (oldname_dateandtime), luego escribo la nueva copia. Luego, apagamos automáticamente nuestro sistema y lo reiniciamos desde un servicio. Cuando se inicia la aplicación, se ejecuta la nueva versión.

+0

Hago lo mismo y borro las versiones anteriores al inicio. –

+0

Dejamos los viejos para que nuestros ingenieros de servicio de campo puedan revertir en el caso de un problema. Por supuesto, tenemos el lujo de los ingenieros de servicio de campo :-). Las versiones antiguas se eliminan en la próxima actualización. –

0

Cuando hice una actualización, debería separar el programa varias. La razón principal era la misma que lo que quieres hacer. Simplemente diga, B actualiza la aplicación de destino más A y A actualiza B. Intenté encontrar otra manera, pero lo que hice fue un actualizador extra pequeño y simple. :(

0

creo que está hablando acerca de las versiones de archivos y actualizadores. como usted ha dicho que necesita autoupdater.So lo necesario para crear un servicio que supervisa el directorio de instalación y compara la versión del archivo en el disco con el servidor.

Una vez desajuste sucede, usted puede pedir últimos datos del servidor. Si los archivos que van a ser reemplazados están en uso hay que marcarlos para su eliminación/eliminación del registro durante el siguiente reinicio y se puede hablar de éstos mediante registro.

puede copiar todos los archivos en la caché y más tarde durante el reinicio, cópialos para instalar el directorio.

4

Así lo hice recientemente. Hay una breve coincidencia del antiguo programa en ejecución y la nueva programación en ejecución. Hace uso del truco de que puede cambiar el nombre del ejecutable actual y poner el nuevo archivo en su lugar antes de cerrar el anterior. Esto no es 100% seguro, pero la única forma en que esto podría "bloquear" su aplicación es si CopyFile falla.

#include <windows.h> 
#include <iostream> 
#include <fstream> 

void UpgradeService::UpgradeSelf() { 

    std::string temp = root   + "\\myprogram_tmp.exe"; 
    remove(temp.c_str()); // ignore return code 

    std::string src = upgradeFolder + "\\myprogram.exe"; 
    std::string dst = root   + "\\myprogram.exe"; 


    rename(dst.c_str(),temp.c_str()); 
    CopyFile(src.c_str(),dst.c_str(),false); 
    static char buffer[512]; 
    strcpy(buffer,dst.c_str()); 

    /* CreateProcess API initialization */ 
    STARTUPINFO siStartupInfo; 
    PROCESS_INFORMATION piProcessInfo; 
    memset(&siStartupInfo, 0, sizeof(siStartupInfo)); 
    memset(&piProcessInfo, 0, sizeof(piProcessInfo)); 
    siStartupInfo.cb = sizeof(siStartupInfo); 

    ::CreateProcess(buffer, // application name/path 
    NULL, // command line (optional) 
    NULL, // no process attributes (default) 
    NULL, // default security attributes 
    false, 
    CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE, 
    NULL, // default env 
    NULL, // default working dir 
    &siStartupInfo, 
    &piProcessInfo); 


    ::TerminateProcess(GetCurrentProcess(),0); 
    ::ExitProcess(0); // exit this process 

    // this does not return. 
} 
Cuestiones relacionadas