Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make a file self-update (Native C++)

I'm using Microsoft Visual Studio 2008 with a Windows target deployment. How would I make a file "update itself"? I've already got the "transmitting over a network" part down, but how do I make an executable write over itself?

Basically, I want to write an auto-updater for a directory that also includes the auto-updater, and the updater needs to update EVERYTHING in the directory.

Maybe a ways to pend the changes to the file for until the file lock is released would work. If I were to do that though, I'd probably follow it up with a hot-patch.

like image 778
Clark Gaebel Avatar asked Jun 17 '09 20:06

Clark Gaebel


2 Answers

Write a new executable and delete or save a copy of the old one -- you could send a diff over the network and have a third program, the update monitor or whatever, to apply it. It would be just a small script that could be started from the remote app when it realizes an update is available. The updater could rename itself to $UPDATER_OLD_VERSION or whatever, write an updated copy of itself with the appropriate name, and then when the new updater is run you check if there is a file named $UPDATER_OLD_VERSION in the app directory and delete it. All other files could just be updated/overwritten.

like image 111
wprl Avatar answered Oct 27 '22 02:10

wprl


This is how I did it recently. There is a brief overlap of the old program running and the new programming running. It makes use of the trick that you can rename the current executable and bring the new file in place before you shut down the old one. This is not 100% fail safe, but the only way this could "brick" your application is if CopyFile fails.

#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.
}
like image 37
Mark Lakata Avatar answered Oct 27 '22 04:10

Mark Lakata