I looked at both Wix and ClickOnce and didn't love them. I wanted something simpler, for one-file "xcopy deployment" type WPF apps.
So I built one. It's an AppUpdater class that you can drop into any WPF app, automatically updates itself when necessary.
Checking for a version number and downloading the latest version is easy.
The next part is less easy. How do you replace a running app? The approach I took was this:
every time it runs, the app checks a well-known URL for a version. If the version is NOT later than the version of the currently executing app, then there's nothing more to do.
If the version IS later, then the app grabs a named Mutex, copies itself (Assembly.GetExecutingAssembly().Location) to a temporary location, then starts a new process (process #2) from that temp location, passing a command-line argument that says "you are trying to update" and giving the original exe location.
process #1 shuts itself down.
process #2 starts up - it sees that it is trying to update, so it downloads the updated image, and places it in the original location (the location that was passed on the command line). Rather than waiting 2 seconds, or any arbitrary time, it uses the named Mutex to determine when process #1 has exited.
process #2 then starts process #3 - using the original location.
Process #2 shuts down, releasing its named Mutex.
process #3 starts up. It checks the version URL - sees that it is current. No update necessary. Process #3 also waits for process #2 to release its Mutex, and then removes the temporary copy of the EXE - the one that was used by process #2.
EDIT
In response to the comment, yes, it sounds complicated. But the logic that does all that is in the AppUpdater module. To use it from a WPF app is pretty simple:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
// add this line in your constructor
if (UpdaterCheck()) this.Hide();
}
// this is all boilerplate
private Ionic.AppUpdater.Wpf.Updater _updater;
private string _manifestUrl = "http://example.org/AppUpdates/MyApplication/Manifest.xml";
private string _infoUrl = "http://example.org/MyApplication.html";
private string _description = "MyApplication is a delightful application; it does x, y, and z. ";
// Obtain the publicKey XML from the ManifestTool that ships with Ionic AppUpdater.
// The following string is Ionic's public key. You will need a different one.
// Consult the Readme for more information.
private string _publicKeyXml = "<RSAKeyValue><Modulus>sZqhvF0KX6m4blah..blah...=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
// add this boilerplate method
private bool UpdaterCheck()
{
_updater = new Ionic.AppUpdater.Wpf.Updater("This is MyApplication.",
_infoUrl,
_description,
_manifestUrl,
_publicKeyXml);
return _updater.Status.IsUpdating;
}
...
Details and code you can run, here.
It works only with WPF apps, but it would be pretty simple to build a WinForms version of the thing. Same idea, though some of the logic that generates the UI would have to change.