7

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.

Clark Gaebel
  • 17,280
  • 20
  • 66
  • 93

7 Answers7

5

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.

wprl
  • 24,489
  • 11
  • 55
  • 70
  • Nope. That solution is too messy for me. I'd rather not have "temp data" floating around. What if the computer crashes in the middle! – Clark Gaebel Jun 17 '09 at 20:41
  • 4
    @wowus - Much better that it crash writing temporary data than overwriting the actual exe. Besides, the fix is easy: Write to a tempfile then call MoveFile to put it in its final location. On the same volume, MoveFile is atomic so a crash won't leave it in an inconsistent state. – Michael Jun 17 '09 at 20:47
  • SoloBold's suggestion is how this kind of thing is generally done. The appliucation you are updating can't update itself. As you say, what if the computer crashes in the middle? – John Dibling Jun 17 '09 at 21:03
4

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.
}
Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
3

You cannot generally modify an app while it is running. You will need to close down the original program and modify it from another location.

muusbolla
  • 637
  • 7
  • 20
2

I do this using an InnoSetup setup.exe that is launched silently and shuts my app down before it starts installing the new files. I had to add custom Pascal [Code] sections to ensure everything shuts down but it does the job.

Rob
  • 76,700
  • 56
  • 158
  • 197
  • Short of writing a device driver or hacking the OS, I think some scheme like this is the only way to do it. When you run an executable under Windows, the OS holds it open write locked. – T.E.D. Jun 17 '09 at 20:49
2

You can't overwrite a file while it's executing, but you CAN rename it. In my updater, I rename the existing exe to something meaningful (oldname_dateandtime), then write the new copy in. Then auto-shut our system down and restart it from a service. When the app starts, it's the new version running.

Bob Moore
  • 6,788
  • 3
  • 29
  • 42
  • I do the same, and clean out old versions on startup. – Marco van de Voort Jun 18 '09 at 08:07
  • We leave the old ones around so our field service engineers can revert in the case of a problem. Of course, we have the luxury of field service engineers :-). Old versions get cleaned out at the next upgrade tick. – Bob Moore Jun 18 '09 at 21:03
0

When I made a updater, I should separate the program several. The main reason was just same as what you want to do. Simply say, B updates target application plus A and A updates B. I tried to find another way but what I did was made extra small and simple updater. :(

Hongseok Yoon
  • 3,148
  • 8
  • 36
  • 51
0

I think you are talking about file versions and updaters. As you said you need autoupdater.So you need to create a service which monitors your install directory and compares the file version on your disk with server.

Once mismatch happens you can ask latest data from server . If the files going to be replaced are in use you have to mark them for deletion / unregistration during next reboot and you can mention these using registry.

You can copy all files in cache and later during reboot copy them to install directory.

anand
  • 11,071
  • 28
  • 101
  • 159