NAppUpdate - Application auto-update framework for .NET

.NET, English posts, NAppUpdate, WinForms, WPF

Comments

5 min read
Any desktop applications programmer finds himself every now and then looking for a library providing an application auto-update functionality, that is flexible and easy-to-integrate. I had the intention of working on such a library for some time now, so it will do things the way I want it to. Last week I got to actually doing it, and I'm quite satisfied with the results. NAppUpdate can be integrated easily with any .NET application - WinForms or WPF, and it offers great flexibility through interfaces, for feed readers, file sources, and update tasks. It also supports conditional updates, the implementation of which offers unlimited extendibility. I based my work on Lee Treveil's .NET-Auto-Update, and although I practically rewrote almost everything, he certainly deserves this credit. The library, released under the Apache 2.0 software license, can be downloaded / cloned from http://github.com/synhershko/NAppUpdate. Please share your thoughts, or any extension you make to it. Update 30/03/2011: A user/developer discussion group is now available at: http://groups.google.com/group/nappupdate

Update 30/09/2010: although most of the post below is still true, it is already (!) a bit outdated. Please check the NAppUpdate tag in this blog for the latest information on the library.

At the time of this writing, here is what NAppUpdate offers:
  1. Seamless integration - one DLL to reference, a few lines of code in the right places and you are all set.
  2. Requires .NET 2.0 and up. No other silly requirements.
  3. Cold updates supported. The updater executable used for replacing files that cannot be hot-swapped is packaged within the library's DLL, and is self-deleting, once done updating.
  4. Shoot and forget, just tell NAppUpdate to prepare and apply your updates once you have notified of their existence, and it will do everything for you, including restarting your application after a cold update.
  5. State-based update process (Did / didn't check for updates; prepared updates; applied updates successfully; rollback required). You can quit any time you wish.
  6. Updates are tasks, so practically every type of update is supported. Right now the only implemented task is FileUpdateTask, used for simple file download and replacement. Implementing more tasks is very easy, and can be done right from your application simply by implementing an interface, without any extra work.
  7. Potentially supported tasks include registry updates, database updates (schema and/or data), Lucene index changes, diff patches, and virtually anything you can imagine.
  8. Backup and rollback are supported in the task level, giving you full protection against failures.
  9. Conditional updates - every task can have unlimited number of conditions attached to it. Conditions are evaluated in a boolean manner, and can be grouped together with AND, OR'd, or being defined as NOT. If the conditions aren't met, the task is being ignored.
  10. Just like with tasks, custom conditions can be created very easily by implementing an interface with your own logic, within your very own application.
  11. Condition types supported at the time of this writing include file properties checks (exists, assembly version, size, date, SHA256 checksum) and OS bitness condition (32/64 bit). More planned conditions include registry checks, more OS checks, prerequisites checks (.NET version and other common applications), etc.
  12. Multiple update feed formats, including Adobe Appcast and our very own NAppUpdate XML (NauXml). You can create your own by simply implementing IUpdateFeedReader.
  13. Abstract download sources allow you to create your own implementation for downloading feeds and update files / packages. Currently we have SimpleWebSource and MemorySource implemented. Your own implementations can include whatever other source you want, for example transfer files over BitTorrent or other P2P protocol.
Here are some code snippets, taken from the WinForms sample application. First is the method checking for updates (UpdateManager.Instance was loaded with some configurations in the Form constructor): [code lang="csharp"] // Get a local pointer to the UpdateManager instance UpdateManager updManager = UpdateManager.Instance; // Only check for updates if we haven't done so already if (updManager.State != UpdateManager.UpdateProcessState.NotChecked) { MessageBox.Show("Update process has already initialized; current state: " + updManager.State.ToString()); return; } // Check for updates - returns true if relevant updates are found (after processing all the tasks and // conditions) if (updManager.CheckForUpdates(source)) { DialogResult dr = MessageBox.Show( string.Format("Updates are available to your software ({0} total). Do you want to download and prepare them now? You can always do this at a later time.", updManager.UpdatesAvailable), "Software updates available", MessageBoxButtons.YesNo); if (dr == DialogResult.Yes) { updManager.PrepareUpdatesAsync(OnPrepareUpdatesCompleted); } } else { MessageBox.Show("Your software is up to date"); } [/code] ... and after a notification on the updates has been sent, and the updates were prepared for installation, here is how this is done: [code lang="csharp"] UpdateManager updManager = UpdateManager.Instance; DialogResult dr = MessageBox.Show( "Updates are ready to install. Do you wish to install them now?", "Software updates ready", MessageBoxButtons.YesNo); if (dr == DialogResult.Yes) { // This is a synchronous method by design, make sure to save all user work before calling // it as it might restart your application updManager.ApplyUpdates(); } [/code] More to come soon...

Comments

  • growse

    Good stuff. I like this a lot.

    One question I had on the FileVersionCondition - if I wanted to apply an update if a local file version was below the currently available, is the only way of doing that to have an 'above' and 'is' wrapped in a 'NOT' boolean? Would it not be more sensible to implement a 'below' condition, to allow out-of-date files to be updated?

  • jumentous

    Itamar,

    I'm about to send through an email for the conversation as i'm about to have to do the changes on my own anyway. I know a list is overkill :), just thought it was a way to make it public if you had a setup already.

    Re:

    1. I was more thinking of allowing design time configuration in VS. Inheriting component etc to add it to a form, adding some events (not a design time req, i know). I was just considering how i would go about enhancing the downloader, particularly to do things like fire an event after each file so that i could show a progress bar for downloading. I thought that it would be nice to drag & drop an UploadManager, a downloader etc onto the form and then assign them. I was looking back through the code though and realize there are a number of place where you reference the Instance from the plugins and don't think the refactoring is worth the gain at the moment.

    2. I'm not using mono but my server is a linux server and i just hadn't thought about adding the BOM which is not in place by default. It would be interesting to see how this behaved under mono, but not today - i'll let you know if i get there.

  • Volker Berlin

    Are there a download of the compiled version? I have see only the sources in the git repository.

    Are there a documentation?

    Must the downloads be signed? Or do you download and install all?

  • kiquenet

    I try download source in github.com.

    but I get error when try download http://nodeload.github.com/synhershko/NAppUpdate/zipball/master

    any suggestions, thanks in advanced, greet tool

  • Brian

    What do you think about using this to update a VB6 application?

  • Norman Paterson

    The example uses an XML file locally, I need to host it on a server. What is that SimpleWebSource you refer to, but I cannot find any instance of??

  • Automatische Updates « Der faule Programmierer

    [...] Open Source technisch gibt es noch NAppUpdate https://github.com/synhershko/NAppUpdate bzw. http://www.code972.com/blog/2010/08/nappupdate-application-auto-update-framework-for-dotnet/ [...]

  • c.y

    i had been wait for whole day. but finally moderator deleted my post... sir,i have setup IIS server then put the .xml file into server with the link http://eramesra.no-ip.org/SampleUpdateFeed.xml then i open the winformssampleApp press the custom feed button and insert the link.but why occur the error with http://imageshack.us/photo/my-images/21/errorqu.jpg/? any support document for tutorial how to setup anything or not?

  • Luis Villalba Campillo

    Hi Sr, is a pleasure to greet...i´m starting to use your library....so i've many questions:

    1. It's work for Windows CE for compact framework applications?
    2. in above case, what´s the path in the naxml file?
  • Luis Villalba Campillo

    Hi Mr. Syn-Hershko, i downloaded the library, samples and the others stuff, so i get an error when i tested the sample WinFormsSampleApp. The exception was about a 'object reference not set to an instance of an object' this, cause the variable 'baseUrl' is null in SimpleWebSource class...i add a condition (if (!string.IsNullOrEmpty(baseUrl)) { if (!baseUrl.EndsWith("/")) baseUrl += "/"; }) so, it worked...is this a bug?

    Another concern is ... where I can parameterize the path where you are downloading the file? ...i mean, the update always is done en the appupdater path...

    thanks a lot...

  • Luis Villalba Campillo

    Hi Sr, thanks for the quick reply ...

    My intention is to use your library for desktop applications and mobile application ... I guess if you set the platform this is possible ... so, what is the mailing list? I would like to discuss the issue ...

    regards ...

  • piotrwest

    If someone is looking for Mono port - I've created working version, but still draft here: https://github.com/piotrwest/NAppUpdateMono.

  • piotrwest

    If someone is looking for Mono port - I've created working version, but still draft here: https://github.com/piotrwest/NAppUpdateMono

Comments are now closed