¿Cómo puede un binario C++ reemplazarse a sí mismo?


Yo hice esta pregunta en un contexto de diseño más general antes. Ahora, me gustaría hablar de los detalles.

Imagina que tengo app.exe corriendo. Descarga update.exe en la misma carpeta. ¿Cómo copiaría app.exe update.exe sobre el contenido de app.exe? Estoy preguntando específicamente en un contexto de C++. ¿Necesito algún tipo de aplicación 3rd mediator? ¿Tengo que preocuparme por el bloqueo de archivos? ¿Cuál es el enfoque más robusto para una actualización binaria en sí (salvo que el personal de TI odioso tenga un archivo extremo permisos)? Idealmente, me gustaría ver soluciones portátiles (Linux + OSX), pero Windows es el objetivo principal.

Author: Community, 2012-02-06

6 answers

  1. Mueva / Cambie el nombre de su app.exe en ejecución a app_old.exe
  2. Mueva / Cambie el nombre de su update.exe descargado a app.exe
  3. Con el siguiente inicio de su aplicación se utilizará la actualización

El cambio de nombre de una dll/exe en ejecución, es decir, bloqueada, no es un problema en Windows.

 40
Author: nabulke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-06 16:02:50

Es una característica del sistema operativo, no una de C++.
¿En qué sistema operativo estás?

En Windows vea la función MoveFileEx () , en linux simplemente sobrescriba la aplicación en ejecución (Reemplazando un ejecutable en ejecución en linux )

 9
Author: Martin Beckett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:25

En Linux es posible eliminar el ejecutable de un programa en ejecución, por lo tanto:

  • descargar app.exe~
  • eliminar corriendo app.exe
  • cambiar el nombre de app.exe~ a app.exe

En Windows no es posible eliminar el ejecutable de un programa en ejecución, pero es posible cambiarle el nombre:

  • descargar app.exe~
  • cambiar el nombre de app.exe a app.exe.old
  • cambiar el nombre de app.exe~ a app.exe
  • al reiniciar remove app.exe.old
 8
Author: Maxim Egorushkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-06 16:05:18

En Windows al menos una aplicación que se ejecuta está bloqueando la suya propia .archivo exe y todos vinculados estáticamente .archivos dll. Esto evita que una aplicación se actualice directamente, at leads si desea evitar un reinicio (si el reinicio está bien, la aplicación puede pasar la bandera MOVEFILE_DELAY_UNTIL_REBOOT a MoveFileEx y es libre de 'sobrescribir' su propia .exe, como se retrasa de todos modos). Esta es la razón por la que normalmente las aplicaciones no buscan actualizaciones por sí solas .exe, pero ponen en marcha una cuña que comprueba si hay actualizaciones y luego se inicia la aplicación 'real'. De hecho, el 'shim' puede incluso ser hecho por el propio sistema operativo, en virtud de un archivo de manifiesto correctamente configurado. Obtenga esto como una herramienta empaquetada de asistente prefabricado, consulte Implementación de ClickOnce para aplicaciones de Visual C++ .

La típica aplicación de Linux no se actualiza a sí misma debido a los muchos muchos muchos sabores del sistema operativo. La mayoría de las aplicaciones se distribuyen como fuente, se ejecutan a través de alguna versión de auto-infierno para auto-configurar y construir a sí mismos, y luego se instalan a través de make install (todo esto puede ser automatizado detrás de un paquete). Incluso las aplicaciones que se distribuyen como binarios para un tipo específico de Linux no se copian a sí mismas, sino que instalan la nueva versión lado a lado y luego actualizan una symbolic link para 'activar' la nueva versión (de nuevo, un software de gestión de paquetes puede ocultar esto).

Las aplicaciones de OS X caen en el cubo de Linux si son del tipo Posix, o hoy en día caen en el cubo de aplicaciones de Mac AppStore que maneja las actualizaciones por usted.

Me gustaría que rodar su propia auto-actualización nunca llegará a la sofisticación de cualquiera de estas tecnologías (ClickOnce, RPMs, AppStore) y ofrecer al usuario el comportamiento esperado vis-a-vis descubrimiento, actualización y desinstalación. Me gustaría ir con el flujo y utilizar estas tecnologías en sus respectivas plataformas.

 2
Author: Remus Rusanu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-06 16:17:24

Solo una idea para superar el problema de "reiniciar". ¿Qué tal hacer un programa, que no necesita ser actualizado. Simplemente impleméntelo en una estructura de plugin, por lo que es solo un host de actualización que a su vez carga un .archivo dll con toda la funcionalidad que su programa necesita y llama a la función principal allí. Cuando detecta una actualización (posiblemente en un subproceso separado), le dice al controlador dll que se cierre, reemplaza el archivo y carga el nuevo. De esta manera, su aplicación se sigue ejecutando mientras se actualiza (solo el archivo dll se vuelve a cargar, pero la aplicación sigue ejecutándose).

 2
Author: Noxoreos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-09 23:26:28

Utilice un ejecutable 3rd actualizador como muchas otras aplicaciones.

  • Descarga la nueva versión.
  • Programe su actualizador para reemplazar la aplicación con la nueva versión.
  • Cerrar la aplicación principal.
  • Updater se ejecuta y hace el trabajo.
  • Updater ejecuta una nueva versión de tu aplicación.
  • Se cierra el actualizador.
 0
Author: Hi I'm Frogatto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-24 20:00:58