Scott Hanselman

How to automatically notify the user that it's time to upgrade a Windows App

March 19, 2014 Comment on this post [51] Posted in Musings
Sponsored By

imageBack in 2007 I did a post called Making your Application Automatically Update Itself. Yesterday I was pairing on a little startup I'm doing on the side with Greg Shackles and it was time do the setup application. I thought about WiX, I thought about InstallShield, but then discovered a wonderful little gem of a setup application called Inno Setup by Jordan Russell. It's free, but it's a joy and you should donate if you use it.

It took me just 15 minutes to make a simple installer, and it's clear that this tool is deep and broad in its support. However, there's no free lunch when it comes to auto-updating. Inno Setup will upgrade my app from build to build when I run a new setup over the top of an old one. I still need my app to notify the user that it's time to upgrade.

This is our little 10 minute solution, but it's actually working very nicely. Inside the latest.txt files is a simple version string like 0.9.9.4.

var http = new HttpClient();
string versionString = await http.GetStringAsync(new Uri("http://www.hanselman.com/SecretStartup/latest.txt"));
Version latestVersion = new Version(versionString);

//get my own version to compare against latest.
Assembly assembly = Assembly.GetExecutingAssembly();
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
Version myVersion = new Version(fvi.ProductVersion);

if (latestVersion > myVersion)
{
if (System.Windows.MessageBox.Show(String.Format("You've got version {0} of SecretStartup for Windows. Would you like to update to the latest version {1}?", myVersion, latestVersion), "Update SecretStartup?", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
Process.Start("http://www.hanselman.com/blog");
}
}

I'm thinking:

  • We'll add an SSL certificate and confirm its identity on the HTTP call as a little added security.
  • Error Handling, natch.
  • One could also download the setup app to %temp%, check it's SHA hash, launch it and close myself. Not sure I like it this automatic, though.
  • Maybe only check the version once a day or once every few days.

Comments?


Sponsor: Big thanks to Red Gate for sponsoring the blog feed this week. Check out the Free Starter Edition of their release management tool! Deploy your SQL Server databases, .NET apps and services in a single, repeatable process with Red Gate’s Deployment Manager. Get started now with the free Starter Edition.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service
March 19, 2014 22:24
You could consider using the same code from the Northern Lights library. You already mentioned this and used this on one of your own WP apps.

http://northernlights.codeplex.com/

No need to re-invent the wheel.

Same concept, but perhaps a little bit more error handling etc.
March 19, 2014 22:25
There's also Squirrel from the GitHub for Windows folks https://github.com/Squirrel/Squirrel.Windows
March 19, 2014 22:25
What about ClickOnce ?
March 19, 2014 22:31
If in any way possible, I use ClickOnce for deployment of apps. Makes all of that a breeze, is integrated into visual studio.
Sadly not that wellknown for what was a nice tech in a pre app-store world.
March 19, 2014 22:34
I used to be BIG into ClickOnce, but I just don't trust it anymore. Not sure why.

I'll check out Squirrel and NorthernLights. Somehow I thought NorthernLights was mostly Windows Phone.
March 19, 2014 22:38
ClickOnce is awesome, why the fallout?
March 19, 2014 22:40
re: auto-download/upgrade - As a product owner/manager, wouldn't it be better to figure out what your customers would like, rather than what you would like? The shift in perspective may just lead to a whole new way of looking at the concept of versions and upgrades which are constructs primarily for the benefit of developers and not the end user.
March 19, 2014 22:42
I noticed that MarkdownPad 2 updates itself automatically like Google Chrome. But unlike Google Chrome it is installed to Program Files and you can see actual installer window running without need of clicking anything. Looks like ideal solution to me.
Pol
March 19, 2014 23:01
Squirrel is pretty great, but still unfinished and a bit buggy. The concept is fantastic, will be awesome when it is done.
March 19, 2014 23:31
Thanks. As a noob, this post confirmed I'm not (totally) clueless :)

I've used Inno Setup (great product) too; and implemented almost the same code to check for updates in my first app. I made it up, and thought it was a bit of an amateur hack (because I made it up) - but seemingly not. I did want to use the VS(express) to create the installer but struggled getting a "single file". Perhaps if I RTFM it wouldn't have been such a problem.
March 19, 2014 23:36
ClickOnce, per this discussion in September 2012:

Here's the most damning aspect of it: if you sign your ClickOnce application (which you are required to or else ClickOnce's installer displays scary "Don't Install This" messages), then the cert expires, every user has to uninstall and reinstall. Completely untenable.
Jed
March 19, 2014 23:44
ClickOnce certificate issues are fixed for the following scenarios:

if your application targets .NET 4.0, or your application is not an Office solution and it targets.NET 3.5 and uses automatic updates, or none of your customers have Windows Vista, you can just replace your certificate, issue an update
Jed
March 20, 2014 0:03
Perhaps Visual Studio should natively include a setup project type to make simple application installers?

OH THAT'S RIGHT. IT DID BUT MICROSOFT KILLED IT AFTER VS2010!!!

Sigh...
AJ
March 20, 2014 0:17
I think this tool (via Itamar Syn-Hershko on Github) might also present an interesting avenue:

https://github.com/synhershko/NAppUpdate

Thanks for this post -- it and the comments present some good choices.
March 20, 2014 0:30
Thanks Sean!
March 20, 2014 0:52
I have seen exactly one Windows application with good and non-annoying update dialog. I think it was one of the latest builds of Paint.NET. Usually I open some file that I'm going to edit right now via context menu (Open with...) and select the editor. Paint.NET starts and immediately shows dialog - "Hey, there is new version available, would you like to download and install it AFTER you finish working with this program?" Also there were some other generic buttons in the dialog. And it indeed updated automatically after I have closed editor.

This was truly epic moment, I know now that there is still hope for humanity and Windows :) .
March 20, 2014 1:21
Well installers are one of those things hard to get right and not fun to write. That's exactly why Microsoft scraped the setup project type in Visual Studio: it was absolute sh*t.

Nowadays MSI is a basic requirement, so WiX is the open source solution if you have more time than money. I for one prefer to rely on the wonderful folks at Advanced Installer. The included updater is small, well thought out, fully featured but flexible and well tested in the wild.

Just thinking about all the scenarios like per-user/per-machine, elevated/non-elevated updates and so on makes my head explode...
March 20, 2014 2:26
One thing to remember is give some time between releases. Filezilla must update every other day.
March 20, 2014 2:27
Try to be more like Evernote for the PC. It gives you the option to skip this upgrade if you want to. It also provides a link to see what's in the upgrade.
March 20, 2014 2:57
On OS X I loved http://sparkle.andymatuschak.org/ which lets you show a HTML file with an upgrade log before the user hits the "Update" button.
March 20, 2014 3:13
Linqpad's auto update is very smooth, you just have a little notification in the top right that there is a new version and I think it does it all seamless in the background (even auto updates normally?")

This is one thing I'd really like to see Microsoft help manage through windows update or something, some kind of built in updater that people could send their url / files to like Nuget for Visual Studio.
March 20, 2014 3:38
Another +1 for Inno Setup. I've been using it for years, and love it.
March 20, 2014 6:43
Now a from all of these tools I know wix can be integrated with builds (tfs)
Click once is a pain to manage in a release environment.

Have you used Inno Setup in a continuous integration build environment before?
March 20, 2014 10:22
There is also NetSparkle (.net port of sparkle cited by Jeena) which is really great, but not maintained since 2011...
March 20, 2014 11:50
@Sergio Romero - I'm using Inno Setup in automated build (just a batch file) so it would work on any sensible CI server.
Pol
March 20, 2014 12:07
I've been using Inno Setup for years on a number of projects. I think a measure of how well thought out it was every time Microsoft introduces some new technology that impacts installation Inno is quickly updated to take advantage of it.

The only downside is no MSI support althought I suspect that is also one of the reasons it is so good.
March 20, 2014 12:30
We're using Inno Setup around here. It's not bad, but Pascal (the language for the scripts) is terribly outdated. I would love to use .Net for that, or any modern language, really. Nevertheless, resources and help are easy to find, and possibilities are plenty.

We have integrated it in Jenkins through Nant. It's not very difficult : you launch "ISCC.exe" with the script path in parameter. We also have a batch to sign our exes and setup packages.
March 20, 2014 17:22
If you Authenticode sign it and do choose to do automatic updates, you should also verify the signature of the downloaded file (though might be overkill if you're going to check the SHA hash).
March 20, 2014 17:50
How about publishing the tool through chocolatey?
Updates are handled through that system then ...
March 20, 2014 17:50
How about publishing the tool through chocolatey?
Updates are handled through that system then ...
March 20, 2014 17:50
How about publishing the tool through chocolatey?
Updates are handled through that system then ...
March 20, 2014 18:32
We started using wyBuild recently and so far it has worked very well. It creates a set of binary differential updates and a "catch all" update so that going from one version to another only requires downloading the changed bytes. Also solves issues with proxy servers and other real world networking problems.

Combined with Inno Setup for initial install and DB Ghost for managing upgrading of database schema and records we have a solid deployment/upgrade solution for our enterprise sized software. Both are commercial systems, but well worth the reasonable licensing fees.
March 20, 2014 19:33
Scott said: "Somehow I thought NorthernLights was mostly Windows Phone."

The Northern Lights link does say, "Northern Lights WP7 Toolkit contains some common tools for WP7 Developers."

BTW, thanks for the code; I'm going to see if I should refactor my auto-update code with it.
March 20, 2014 19:34
Scott said: "Somehow I thought NorthernLights was mostly Windows Phone."

The Northern Lights link does say, "Northern Lights WP7 Toolkit contains some common tools for WP7 Developers."

BTW, thanks for the code; I'm going to see if I should refactor my auto-update code with it.
March 20, 2014 20:12
Sorry for the stuttering; there was a hicc[ough,up] that made me think my first attempt to post had been lost in the ether, visible only to the NSA.

Nayway, here is my gist showing how I download updated files to a Windows client from an ASP.NET Web API server app:

https://gist.github.com/bclayshannon/9667160
March 20, 2014 22:33
I've been using NSIS for some time, then switched to INNO as NSIS is commonly identified as suspicious by antiviruses ;) You can write your own plugins for INNO so it's pretty extensible. We've also used it to silently update our application which is pretty the same process as uninstall and install again.
March 20, 2014 22:47
I'd like to hear more about why you don't trust ClickOnce. I just started using it for some internal tools after hearing "bad things" for a while. It seems fantastic, actually.

However, with your solution, since you're rolling your own, you might want to have a "Stable" and a "Beta" line, like "Stable:0.9.0.0" and "Beta:0.9.9.4", giving yourself "channels" like Chrome, so that you can have power users select a Beta channel and get updates faster to help you iterate if they aren't afraid of possible bugs. This also lets you test internally with a Dev channel.

I also like the idea of silently downloading the installer and executing it silently when the program closes or tell the user via an unobtrusive icon that one is available (again, a la Chrome). When you ask the user to make a decision, the user typically chooses the path of least resistance (clicking "no" or "later").

I'm not sure who the audience of SecretStartup is though. Knowing you, it is probably a more technical audience, but I think we all enjoy Chrome's update mechanisms.
March 20, 2014 22:48
ClickOnce is a setup developer's opportunity to shift all the complexity on to your end users. This is fine if you're delivering an in-house application because the environment is constant and predictable.


  1. ClickOnce is basically a black boxed version of XCopy; it leaves you with few recourses for your end users if something goes horribly wrong during an upgrade (1 in a million is next tuesday). There's no way to drive people back to your site or contact number if something goes wrong, either, so instead of making communication easier it does the opposite in my experience.


  2. ClickOnce certificates are a nightmare. Issuing new certificates is easier said than done when people are hosting your CO installer in a disconnected environment. Installers should validate via hashes, leave certificates to the OS.


  3. ClickOnce has virtually no support for customized installations. You need something special done? Hope you're good at updating app.config files. Which by the way can get blown away by all kinds of standard things; i.e. adding files. Also MAGE is just so complex to use and requires all sorts of magic handshakes to get an application built if you don't toe the standardized line.


  4. It's sloooowwwww. I can install /qb MSIs faster than our ClickOnce project.




This coming from ~8 years of varying degrees of install dev support, writing updaters, installation dev, etc. I've seen most of it all :-)

Also Chrome has the right update experience. I don't know why apps even bother to ask a majority of the time. When I close the app it should update - with an indicator it wants to do so. If you need to set out of band updates (say major upgrades not chrome style) then approach those ad-hoc. But a majority are just like "Would you like to install these critical bugfix/security patches we released?"

From a dev point of view, any time you make an update optional people won't install it. I wish I could access the very depressing A/B testing we accidentally did on this, but it's blocked. Perhaps others' mileage varies, but this was several widely distributed consumer apps :)
March 20, 2014 22:53
@Radosław Zawartko - I used NSIS for some time too but switched back to Inno. One of reasons is that Inno installers look very normal without extra effort.

@Thomas - Inno itself is written in Delphi (Object Pascal). I like both Object Pascal and C# (peace) :)
Pol
March 20, 2014 23:01
Going back to Google Chrome, they use ClickOnce I believe because this way it is less warnings before running installer but I don't think that actual installer is just ClickOnce. What about writing ClickOnce launcher/wrapper of Inno installers to have best of both words? Good idea? :)
Pol
March 21, 2014 14:26
This might be a personal preference, but one of the updating systems I get annoyed by are the ones where you get prompted at the startup of your application, and have no other options except either updating now, or not at all (continuing the cycle).

If I open the application, I want to use it. Rarely will an update be interesting enough for me to actually perform it before I get to do what actually I intended to do when opening the application.

If I open a video file in VLC, I'm not interested in updating, I'm interested in watching a video. Exceptions can be made for seriously important updates (security-wise) or actually required updates (an online multiplayer game needs to be updated asap so as to be able to connect to the game servers), but definitely not for every update imagineable.

I'd love it more if those types of questions were asked either at the end of the application (shutting down, then mentions it can update itself), or allowing the prompt at startup another option, i.e. to download the update in the background and start installing it when the application is being shut down.

Am I overlooking something?
March 21, 2014 16:29
I agree with Flater, if I start an application I never want to update it at that moment, so a very unintrusive way to tell me that there is an update (like e.g. Github for windows does it) is key for me.

There's another thing which hasn't been mentioned yet: with this autoupdate system, the software vendor can also track the number of times a tool is used and by whom and when (one can send as much info as possible in the call to the service to check whether there's a new version, it's unclear what's being send).

As a software vendor this is great, as a user I definitely don't like it: I don't want to leak whatever I do on my PC to whatever 3rd party is out there. This is one of the reasons I haven't implemented it yet in my own software, although as an ISV I'd be very interested who uses the software when and how many times a day.

So IF a vendor is implementing it, at least add an option to disable this. Which mitigates the feature, I know, but it also gives more peace of mind. At the moment I have no idea what is send along the 'phone home' request in various apps.
March 21, 2014 20:29
I also have some code out there on GitHub for this scenario. It is older but it is stable.

The main reason I didn't like ClickOnce is because your application is no longer a real application.

You can check out my simple updater here:

http://jvance.com/pages/SimpleUpdater.xhtml
March 21, 2014 22:10
For all the people advocating ClickOnce, be aware it doesn't work with roaming profiles.
That rules it out for use in terminal services and a lot of domain environments. For me if it doesn't work for all user profiles it doesn't work.

It doesn't work because ClickOnce apps install into %localappdata%\Apps only the local app data folder isn't stored in your roaming profile so when you log off you lose the install. We have an app that does this at work and its an absolute nightmare.

What we really need is a way for windows (desktop) apps to register for updates. Then windows takes over downloading and where possible installing updates.
March 24, 2014 0:55
You could keep notes on all your projects all over
the room. Remember to include luxurious sheets and blankets, plush
pillows, and most importantly, a comfortable mattress.
Stays super sharp with just a little touch up now and the with included honing
steel.
March 24, 2014 12:04
We use Innosetup for years now, after having used installshield (which is hell, both because it's way to complex to use and because it costs piles of money for each version and update that you need in anyway for each new windows version) and even tried Wix. Innosetup is simple, works always, and integrates nicely (via an extension) in Visual Studio, which makes building a setup just one click extra after finishing the application.
With installshield, setup creation had to be part of the planning and took a reasonable amount of time. With innosetup, building a setup for our software is a task that takes little or no time and it allowed us to create an environment for automatic publishing/distribution of our software via central web service that publishes versions for the different modules.
wvh
March 24, 2014 21:59
No msi? Is this the dark ages?
March 26, 2014 20:03
Good Article!

But every solution has it's downsides:

MSI: Single instance install induces problems with multiple software installing at the same time, like when Windows Updates decides it's that time of the week. Working with different tech support teams saw a lot of issues with crashed Windows Installer Service that would no longer respond (solution was to un-register the service and re-register it). Also there's a chance Windows Installer is in a limbo state (Restart needed for changes to take effect). Sadly MSI is far from stable or perfect even for Microsoft products. Also MSIs use CAB compression and these are not the dark ages. Now we have proper compression algorithms and huge processing power / memory.

Other installer scripts (NSIS, Inno Setup, etc) seem to work more or less on the same principle.

Clickonce: Installer main purpose is to install prerequisites. Using Clickonce you suppose the user already has a Clickonce compatible .NET Framework version ( and you would be wrong in lots of cases where users own an XP OS )

If your app has nothing complicated to deploy, you'd be better off having a self-extracting archive :)

As for updates:
After many experiments it seemed like a really bad ideea to trigger updates at system startup - I've experience a multitude of issues like really bad internet connection, a lot of processes hugging up the whole memory ( like Antivirus engines, Chrome etc) leaving your app prone to weird issues.
Don't ask the user for an update. Everyone hates it, especially when they are starting your app. If you can, download the new version silently, store it side by side with your app, and trigger a swap between the current version and the update at the next app launch. If something fails, make sure you can rollback.

Make sure you have some kind checksum in order to check if the thing you downloaded is not corrupt. Don't give up on the first try, retry the downloads. Catch exceptions.
If you want to optimize you could always use Torrents depending on your app size. Download update patches instead of full version. Download binary differences instead of files.

Statistics. You should be able to track everything. Be able to update the update system. Unexpected errors happen ALL the time.
March 28, 2014 5:57
I used Inno for this purpose for a number of years to update an older (sigh) VB application in an enterprise environment and it worked great.

Something to always consider about updating a user's software in this way is a user's permission level. I have written (more than once) frameworks that do things like performing the check in user context, while performing the installation under system context to avoid any untidy group policy lockdown issues.

Inno and the technique above have really helped us to extend the usability of windows applications in a web application world.

P.S. Friends don't let friends use ClickOnce
March 30, 2014 16:43
You have made interesting discoveries and realize that it is valuable and unique.
June 14, 2014 3:26
can you link "a little startup I'm doing on the side" to the actual startup landing page

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.