29

I asked this question in a more general design context before. Now, I'd like to talk about the specifics.

Imagine that I have app.exe running. It downloads update.exe into the same folder. How would app.exe copy update.exe over the contents of app.exe? I am asking specifically in a C++ context. Do I need some kind of 3rd mediator app? Do I need to worry about file-locking? What is the most robust approach to a binary updating itself (barring obnoxious IT staff having extreme file permissions)? Ideally, I'd like to see portable solutions (Linux + OSX), but Windows is the primary target.

Community
  • 1
  • 1
TheBuzzSaw
  • 8,648
  • 5
  • 39
  • 58
  • As far as I know, Windows will not let you overwrite an EXE while the program is running. This is one of the most annoying things in Windows, imo. – unwind Feb 06 '12 at 16:01
  • 1
    As I told you on that other question, you cannot overwrite an exe thats running. I even gave step by step instructions on how to do this entire process. – Mooing Duck Feb 06 '12 at 16:27
  • @MooingDuck I know! I'm still referencing your answer as a high level design. I'm simply narrowing the scope for this particular question. Already, I'm fairly pleased with the answers. – TheBuzzSaw Feb 06 '12 at 17:29

6 Answers6

46
  1. Move/Rename your running app.exe to app_old.exe
  2. Move/Rename your downloaded update.exe to app.exe
  3. With the next start of your application the update will be used

Renaming of a running i.e. locked dll/exe is not a problem under windows.

nabulke
  • 11,025
  • 13
  • 65
  • 114
10

On Linux it is possible to remove the executable of a running program, hence:

  • download app.exe~
  • delete running app.exe
  • rename app.exe~ to app.exe

On Windows it is not possible to remove the executable of a running program, but possible to rename it:

  • download app.exe~
  • rename running app.exe to app.exe.old
  • rename app.exe~ to app.exe
  • when restarting remove app.exe.old
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
9

It's an operating system feature - not a C++ one.
What OS are you on?

In Windows see the MoveFileEx() function, on linux simply overwrite the running app ( Replacing a running executable in linux )

Community
  • 1
  • 1
Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
2

Just an idea to overcome the "restart" problem. How about making a program, that does not need to be updated. Just implement it in a plugin structure, so it is only an update host which itself loads a .dll file with all the functionality your program needs and calls the main function there. When it detects an update (possibly in a seperate thread), it tells the dll handle to close, replaces the file and loads the new one. This way your application keeps running while it updates itself (only the dll file is reloaded but the application keeps running).

Noxoreos
  • 23
  • 5
2

On Windows at least an application running is locking its own .exe file and all statically linked .dll files. This prevents an application from updating itself directly, at leads if it desires to prevent a re-boot (if re-boot is OK the app can pass in the MOVEFILE_DELAY_UNTIL_REBOOT flag to MoveFileEx and is free to 'overwrite' it's own .exe, as is delayed anyway). This is why typically applications don't check for updates on their own .exe, but they start up a shim that checks for updates and then launches the 'real' application. In fact the 'shim' can even be done by the OS itself, by virtue of a properly configured manifest file. Visual Studio built application get this as a prefab wizard packaged tool, see ClickOnce Deployment for Visual C++ Applications.

The typical Linux app doesn't update itself because of the many many many flavors of the OS. Most apps are distributed as source, run trough some version of auto-hell to self-configure and build themselves, and then install themselves via make install (all these can be automated behind a package). Even apps that are distributed as binaries for a specific flavor of Linux don't copy themselves over, but instead install the new version side-by-side and then they update a symbolic link to 'activate' the new version (again, a package management software may hide this).

OS X apps fall either into the Linux bucket if they are of the Posix flavor, or nowadays fall into the Mac AppStore app bucket which handles updates for you.

I would day that rolling your own self-update will never reach the sophistication of either of these technologies (ClickOnce, RPMs, AppStore) and offer the user the expected behavior vis-a-vis discovery, upgrade and uninstall. I would go with the flow and use these technologies in their respective platforms.

Remus Rusanu
  • 288,378
  • 40
  • 442
  • 569
  • What about applications that run continually? In my case, the app runs all the time and actively probes for updates (in addition to performing its various tasks). Would you still recommend using those same update tools? – TheBuzzSaw Feb 06 '12 at 17:31
  • IS the app user interactive or daemon/service ? User interactive apps like ClickOnce can notify the user. daemon/service type depend on the environment: in an enterprise environment they are updated by admins, who are very reluctant on apps to automatically download and run new bits (untested, and more importantly, potentially compromised). A consumer daemon/service would have an easier time selling the benefits of self-update. – Remus Rusanu Feb 06 '12 at 17:35
  • I would classify it as a daemon/service. Fundamentally, it is there to extract data (as permitted by the user). However, bugs pop up. A random example might be that people's names are coming in backwards. I want to be able to push out a tiny bug fix without all the frills of a full-blown software install. – TheBuzzSaw Feb 06 '12 at 17:48
  • 99% of the times the software will run under restricted privileges and won't be able to update itself w/o the user acknowledging an elevated context ([sudo](http://en.wikipedia.org/wiki/Sudo), [UAC](http://msdn.microsoft.com/en-us/library/windows/desktop/aa511445.aspx), [Authorization framework](https://developer.apple.com/library/mac/#documentation/Security/Reference/authorization_ref/Reference/reference.html#//apple_ref/doc/uid/TP30000826-CH202-DontLinkElementID_2)) – Remus Rusanu Feb 06 '12 at 17:58
0

Use an updater 3rd executable like many other apps.

  • Download new version.
  • Schedule your updater to replace the app with the new version.
  • Close main app.
  • Updater runs and does the work.
  • Updater runs new version of your app.
  • Updater quits.
frogatto
  • 28,539
  • 11
  • 83
  • 129