Applet Mitigations – Updaters


So how do you make an updater be less horrible.

First off, as I suggested for all applets, consider not having one at all.  For instance, Collectorz.Com‘s applications each check for updates periodically when they are started.  That way you bury your update functionality with the application, and it alleviates the need to worry about external updaters.

If your application is itself a plugin (think Flash, Quicktime, Java or a driver (of any kind)), then you don’t have a convenient application on which to hang your updater.  For that case, whatever you do, don’t burn a process whose sole purpose is to check for updates once a month.  Instead, use the task scheduler functionality built into Windows to schedule your updater. The task scheduler is a remarkably flexible mechanism for scheduling periodic operations.  Even using the Task Scheduler 1.0 interfaces (which are available on Windows platforms going back to Windows ME), you can generate triggers that will cause tasks to be run daily, weekly, monthly, monthly on a specific day of the week, logon, idle, etc.  For Vista, the list of trigger types is enhanced to include triggers on system events, groups of triggers, etc.

One of the cool things you can do with scheduled tasks is to specify the context in which the job runs – jobs can be scheduled to run in the context of the user at the console, in the system context, the context of an interactively logged on user, to run only if a specific user is logged on, etc. 

Using the task scheduler means that you can get your updater to run without consuming any long-term resources.

 

Once you’ve decided that you need to update the application, you’ve got to download the update.  For that, you really have two options.  The first is that you can assume that the user is going to want the update and pre-download it, the second is that you download it after informing the user about update.  For either case Windows has a nifty feature called “BITS” which allows you to download data from the web without interfering with the user – essentially the BITS service is aware of the traffic generated by the interactive user and it throttles its transfers if it detects that the user’s using the network.  It also supports progressive downloading so it can handle the network dropping out mid transfer.  Windows Update’s downloader is built on top of BITS, but I’m not aware of any 3rd party apps that use it (which is a shame, because it really is cool).  BITS is available on at least Windows XP and later, so it’s not “yet another vista-only feature”.

Also, whatever you do, don’t ever require elevation for your updater – I cannot imagine any scenario that would require that your updater run elevated – it just annoys the user who complains about unnecessary elevation prompts.

 

Next: Mitigations for notification area handlers.

Comments (24)

  1. Dean Harding says:

    One problem I had with BITS is that it only considers the local network adapter when determining when the connection is "idle". The problem with that is, my network adapter is 100 Mbit, but my internet connection is much slower than that. So even if I’m downloading a file at "full" speed, BITS sees that much of my "network connection" is idle and tries to download as well.

    Looking at the documentation, though, that seems to be fixed in BITS v3 — included with Windows Vista. I think I’ve got UPnP turned off, though, so maybe it’s time to enable it :-)

  2. >  I cannot imagine any scenario that would require that your updater run elevated

    Uh, this one lost me. I write my installer to install in Program Files. Surely that means my updater must update files (DLLs, EXEs, say) in Program Files? Ergo, elevation, no?

    Cheers. Julian

  3. Scott says:

    A great Media Center program, <a href="http://www.tvtonic.com">TVTonic</a&gt;, basically a video podcast client, uses BITS.

  4. Tim says:

    That is pretty much what i implemented for the application i work on, the IT guys for our clients were getting annoyed with always having to run updates on the locked down machines, so i implemented a system utilizing Duncan McKenzie’s BITS wrapper for .Net.

    The application checks for available updates at startup on a background thread and if available it initiated a BITS job. When an update is available and downloading an icon appears in the toolbar at the right hand side (a la the original firefox) and the user can click on it to see the status.

    It downloads a valid MSI package and utilizing the wixcab.dll i have it so that it extracts the files from the MSI and updates the software when the app is closed (giving the user 5 seconds to skip the update, as well as a button to allow them to not have to wait). Using the official MSI gives less chance of versioning issues as we only have to deploy 1 update package (with a price of slightly larger downloads).

    There are two caveats

    1) All users have to have full control to the program directory but thats not toooooo bad and can be configured at install time).

    2) Some machines seem to have a problem with BITS and i am still debugging those issues.

    Oh and naturally the automatic updating can be disabled :)

  5. Marvin says:

    "Windows Update’s downloader is built on top of BITS, but I’m not aware of any 3rd party apps that use it (which is a shame, because it really is cool)"

    Maybe this is because it wasn’t cool enough to be documented…

  6. Zian says:

    There are at least 3 apps that use BITS besides Windows and Office. RSS Bandit is one of them.

    See http://en.wikipedia.org/wiki/Background_Intelligent_Transfer_Service for details.

  7. jon says:

    If you’re installed in the Program Files folder, how could you possibly update yourself WITHOUT elevation on Vista?

  8. LarryOsterman says:

    Marvin, I included the link to the BITS documentation.

    jon: You can check to see if an update is available without elevation, then elevate only if an update is needed.

  9. Dean Harding says:

    Re not requiring an elevation prompt for updates, you might be able to do it with this: http://msdn2.microsoft.com/en-us/library/aa372388.aspx

    That page is rather confusing, but I do remember seeing something about administrators being able to specify applications that are allowed to be patched by non-administrators using digital certificates and so on…

  10. davidacoder says:

    Is there a reason Windows Update doesn’t use the suggestion you make here? It runs as a service, instead of using the task scheduler. I assume there is a good reason for that, and knowing that reason might be a good indicator why third party ISVs also do it that way.

  11. Thorsten says:

    "…BITS, but I’m not aware of any 3rd party apps that use it."

    The launchpad application of the StarWars Galaxies MMO uses BITS to start downloading the files for the next update a few days before it officially goes live.

  12. Tanveer Badar says:

    ‘Uh, this one lost me. I write my installer to install in Program Files. Surely that means my updater must update files (DLLs, Exes, say) in Program Files? Ergo, elevation, no?’

    Julian, but why would you restrict your user to install only to Program Files?

    If a non-admin user installs to some other location, he/she will have write permissions for that directory for future updates too.

    If an admin install to Program Files, he/she already has the necessary permissions for future updates and the updater may only run in the elevated context.

    I am down with all programs which require admin users for installation, only because their setup has %programfiles% hard-coded as the base directory. Half of my line of business programs don’t run under user accounts because they constantly write to the installation directories which unfortunately lie at %programfiles%.

    As some examples: Flashget won’t save download information for files because it writes to [installationdirectory]default.jcd which is usually in %programfiles%. Firefox fails to update by non-admin users because it too goes to %programfiles%. My bug tracking software fails to connect to server because it writes credentials to a file in installation directory, which again is in %programfiles%.

    That is not just for programs out there in the wild; Microsoft products do have that problem too. Any ASP.Net project that uses IIS must be opened in Visual Studio running under admin account, do run-as, privilege escalation whatever! MSN messenger displays only an update notification that tells to login as an admin.

    And Dean, Microsoft does not follow the guidelines they have laid out for others themselves.

  13. twoelfer says:

    >> but I’m not aware of any 3rd party apps that use it

    well, we do :-) ( http://www.die.de/docs )

    WM_FYI

    -thomas woelfer

  14. Chris Smith says:

    Even if the application is installed in Program Files, I don’t see any reason why a well-designed updater should need elevation at all – it can execute in the system context to actually perform the installation (assuming the file transfer is itself secure, and/or you check for a valid digital signature on the download).

    So basically:

    1) Use Task Scheduler to launch your update-checker on occasion. The update-checker deals with Internet resources, so should ideally run with limited privileges.

    2) If an update is found, download it via BITS, and then trigger your actual update process in a context with high privileges (e.g. LocalSystem) via Task Scheduler.

    3) If you want to block on user input (e.g. to accept the upgrade and begin installation), launch a separate, low-privilege process in the user(s) context for the UI. This would signal back to the high-privilege process a simple "proceed/cancel" message (hence limited attack surface).

    4) The high-privilege updater process would either exit if it gets the cancel message, or proceed with the installation (verifying that the digital signature of the update is both yours and the file integrity is good, so the file cannot be faked by another publisher).

    5) During the update, which is done by the high-privilege non-interactive process, you could optionally post progress updates back to the low-privilege UI process if you want the user to be aware of the status.

  15. AndyC says:

    Tanveer, that’s not necessarily true if an Administrator installed the program on behalf of someone else. Using signed v4 MSIs that have been designed for user patching is a really good solution to this. Alternatively, if you are using the Task Scheduler approach, you can arrange for the task to be created in a context which does have the necessary rights.

  16. Leo Davidson says:

    > Uh, this one lost me. I write my installer to install in Program Files. Surely that means my updater must update files (DLLs, EXEs, say) in Program Files?

    Your *installer* might write to program files and require elevation but your *updater*, which checks for an update and then downloads it and runs the installer, shouldn’t.

    I think Larry’s point is that you really don’t want to be hassled by a UAC prompt when an updater decides to wake up and do an update check. A couple of posts back he mentioned something which did just that.

  17. Marc Bernard says:

    >> but I’m not aware of any 3rd party apps that use it

    So do we.  Our field service folks are mighty happy about it.

    http://www.agfa.com/usa/en/he/products_services/all_products/impax_60.jsp

  18. LarryOsterman says:

    davidacoder: I’m not sure why WU is a service, I’ll see if I can find out.

  19. Grant says:

    "Maybe this is because it wasn’t cool enough to be documented…"

    Why do people embarrass themselves like this? A little research shows that there is a large amount of information on the Internet on using BITS, including formal documentation. In addition to the link to the documentation Larry provided, there is:

    Write Auto-Updating Apps with .NET and the Background Intelligent Transfer Service API:

    http://msdn.microsoft.com/msdnmag/issues/03/02/bits/

    Background Intelligent Transfer Service (BITS):

    http://download.microsoft.com/download/b/3/d/b3d8e8ea-8c3f-4962-8a01-478b33f44e15/BITS.doc

    Using Windows XP Background Intelligent Transfer Service (BITS) with Visual Studio .NET: http://msdn2.microsoft.com/en-us/library/ms997639.aspx

    Managed Wrapper for BITS:

    http://www.duncanmackenzie.net/blog/Managed-Wrapper-for-BITS/

    Maybe some of the above isn’t applicable to you, maybe it is. Point being, to claim that Microsoft does not document (and support developers using) it’s *public* APIs is an outright lie and does a disservice to the men and women of Microsoft who work very hard to try to make sure the documentation is complete:

    http://channel9.msdn.com/Showpost.aspx?postid=331844

  20. Mike Dunn says:

    Shameless plug for an article I wrote that demonstrates how to use BITS to download files:

    http://www.codeproject.com/wtl/wtl4mfc9.asp

  21. Jerry Pisk says:

    Somehow I think Larry meant that the application that checks for updates and downloads them should not need elevation, not the actual update itself.

  22. Mihai says:

    "I’m not sure why WU is a service, I’ll see if I can find out."

    It is called "Automatic Updates"

  23. Norman Diamond says:

    > two options.  The first is that you can assume that the user

    > is going to want the update and pre-download it,

    DO NOT DO THIS.

    Windows Automatic Updates provide correct options for this kind of thing.  If the user sets an option to do pre-downloading then you do it.  But DO NOT ASSUME IT.

    It is really fun (not) to dial up a cell phone, expecting to spend a few seconds downloading or sending e-mail, and finding that some assumer has hijacked your connection.  The train is leaving the station in 40 seconds.  You want to download updates tonight, not now.

    It is really fun (not) to find assumers doing the same thing on a pay-per-packet internet connection.

    History question:

    > Task Scheduler 1.0 interfaces (which are available on

    > Windows platforms going back to Windows ME)

    Does that mean 98 had Task Scheduler 0.0 interfaces?

  24. In previous articles, I&#39;ve pointed out: Programmer Hubris – He&#39;s just not that into you Programmer