19

Launchers are most common in games. Think of League of Legends, Starcraft II, or almost any MMO out there. Before starting the actual game, you have a small launcher app that takes care of updates and patching.

I want to move this direction with a particular non-game application I am developing. The concept of the launcher makes perfect sense: it checks for updates, replaces the appropriate binaries/libraries, maybe runs an integrity check, and launches the application. However, how do launchers update themselves? This tends to be a rare event, but how is it done? Does the launcher literally just write over the very binary it is currently running from? Or is there some kind of swap step after the download? I need to be able to push out (rare) updates to the launcher (especially if I discover some bug in my launcher).

My particular project will be in C#, but I am interested in conceptually similar C++ and/or Java solutions as well for future reference.

TheBuzzSaw
  • 8,648
  • 5
  • 39
  • 58
  • 1
    Once a program is loaded into memory, it shouldn't really care whether what happens to the binary image file from where it came, so you should be allowed to overwrite that. Then all you need to do is relaunch the program, perhaps with something like `exec`. – Kerrek SB Jan 20 '12 at 16:51
  • @KerrekSB Sounds simple enough. I'm still a tad fuzzy on that final step though. So, run the program in a separate process and then just exit? – TheBuzzSaw Jan 20 '12 at 16:54
  • 5
    @KerrekSB, Windows locks the executable file while it is running. Partially because some sections may not load immediately. – Gayot Fow Jan 20 '12 at 17:02
  • When I read this, I really wonder what problem the launcher solves in the first place. If you are going to write a self-updating program anyways, why not just avoid the launcher completely? – André Caron Jan 20 '12 at 19:12
  • 1
    @AndréCaron: It's a smaller executable, faster to open and generally has another purpose than the main program. – Xeo Jan 20 '12 at 19:26
  • @TheBuzzSaw, will all your users have admin privs? – Gayot Fow Jan 21 '12 at 00:35
  • @GarryVass - No. Why do you ask? – TheBuzzSaw Feb 05 '12 at 23:13
  • @TheBuzzSaw, will your launcher then run as full trust? – Gayot Fow Feb 06 '12 at 13:07
  • @GarryVass I can't say. My client base is extremely varied. I assume it will run as full trust in most cases. Part of the purpose of this launcher is to move away from pushing out MSI updates in favor of just downloading/updating DLLs. – TheBuzzSaw Feb 06 '12 at 15:51
  • Generally a launcher would need privileges to modify executable files, but no more. The "main program" doesn't need any special privileges. – Mooing Duck Apr 09 '13 at 16:42

3 Answers3

7

I've never tried, but this is what I would guess (assuming you can't overwrite a file being executed. If you can, this is all simpler)

Updater A checks if its the newest version
If launcher isnt the newest version
    Download the differences (to save bandwidth) to file B
    Apply the delta to own code into file C
    Launch file C.
    Close
If file C exists (update happened recently)
    Try to delete C  (update was previous launch, delete temporary file)
    If delete fails  (We are C, means A is out of date)
        Copy C over A  (update launcher)
        Note that you can keep going, dont have to restart even though we are C.
If game isnt newest version
    Download the differences (to save bandwidth) to file B
    Apply the delta to game into file D
    delete game
    Rename D -> game
Run game

André Caron has shown me that the swap trick is done better with transactional file IO.

Dave
  • 12,117
  • 10
  • 46
  • 52
Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
  • This definitely gives me some ideas. I'm mulling them in my head right now. – TheBuzzSaw Jan 20 '12 at 17:33
  • If the connection is disrupted? – Gayot Fow Jan 20 '12 at 18:12
  • 1
    @GaryVass: I thought the temporary files took care of that. Do you see a flaw in my design somewhere? All downloads are to a separate file `B` until complete, and then applied to another file `C`/`D` until complete before execution. – Mooing Duck Jan 20 '12 at 18:59
  • What does the "no fail swap trick" bit refer to? How can two successive renames be guaranteed to work? (on windows, you can always use filesystem transactions, but I'm not assuming this is what you mean). – André Caron Jan 20 '12 at 19:09
  • @AndréCaron The swap trick is a common way of swapping internals of objects in C++ in a way that cannot fail. This is based on that. The renames _could_ fail in this case, but it's trivially recoverable (even for power failure). If you were to copy a file over the other instead and a power failure occurred, that _cannot_ be recovered from. – Mooing Duck Jan 20 '12 at 19:14
  • 1
    @MooingDuck: I'm aware of the C++ version, I wondered if there was some similar trick for files. You are approximating transactions, but they are not truly fail-safe. Check out [transactional NTFS](http://msdn.microsoft.com/en-us/library/windows/desktop/aa365738.aspx). – André Caron Jan 20 '12 at 19:20
  • @MooingDuck, re your design, it's roughly the same as Steam's and look where it got them... http://www.google.co.uk/search?sourceid=navclient&ie=UTF-8&rlz=1T4SVED_en___GB438&q=steam+doesn%27t+start – Gayot Fow Jan 21 '12 at 00:22
  • @GarryVass: Is that a design problem or implementaton problem. I'd assume this is the same design as every other launcher in Windows. – Mooing Duck Jan 21 '12 at 03:47
  • Why wouldn't `Delete game; Rename D->game` be failure-recoverable? You have the up-to-date file in D, so even if afterwards you fail at any step, it doesn't matter if game is destroyed/corrupted. You still just need to delete game and rename D to game. No? – Shahbaz Apr 09 '13 at 16:30
  • @Shahbaz: Actually, you're right. I'm just used to copy-and-swap in everything else I do, that I failed to notice in this particular case it doesn't make anything easier. – Mooing Duck Apr 09 '13 at 16:39
2

If you are in the .NET world, there is a deployment strategy called 'Click Once'. This was created to solve the problem you have described...

ClickOnce is a deployment technology that allows you to create self-updating Windows-based applications that can be installed and run with minimal user interaction. ClickOnce deployment overcomes three major issues inherent in deployment:

Source: Click Once

Before embarking on this strategy, I suggest researching its pros and cons because there are avid fans and detractors.

Briefly, you upload new versions to a web site (which the application is configured to know about). At start up time, the application checks the site and if there's an update offers the user a dialog. When the user elects to apply the update, the application is stopped and simultaneously a 'click once' component is activated to apply the changes. The component then restarts the executable and this all appears as a seamless operation to the end user...

Gayot Fow
  • 8,710
  • 1
  • 35
  • 48
  • 2
    Thank you for sharing this. I'll look into ClickOnce, but I am still interested in seeing direct code-based solutions. I'd like to understand the process conceptually should I ever need to code it myself. – TheBuzzSaw Jan 20 '12 at 16:47
  • 1
    I think OP was looking for techniques used to implement systems like that one. This doesn't explain how updating the launcher is achieved. You still have to update the "Click Once" launcher somehow anyways. If it auto updates itself, then maybe you could elaborate on how this is achieved? – André Caron Jan 20 '12 at 16:48
  • @AndréCaron, the link gives a very clear explantion of how the launcher updates itself. I suggest reading it and then returning with any remaining questions you have – Gayot Fow Jan 20 '12 at 16:53
2

Basically the launcher checks to see if there is a newer version of it self, and if so kicks off a task to get the new version and then executes it and then closes.

Given the updater app is small and loads up quick, you can have it detect, download, stick up a dialog to say there's a new version, and barely flicker as the old version closes and the new one runs up.

Tony Hopkinson
  • 20,172
  • 3
  • 31
  • 39