Demistify the ClickOnce update story

Updates for ClickOnce apps are controlled by the following XML tags in the Deployment manifest.

                <expiration maximumAge=”6″ unit=”hours” />

<beforeApplicationStartup> and <update> are mutually exclusive functionality wise though not in Schema. When both tags are present <beforeApplicationStartup> wins.

BeforeApplicationStartup –
When this tag is present in an application’s deployment manifest, at every activation of the application via the desktop shortcut, Clickonce does an update check. If no update is available the application is launched else the Update confirmation Dialog (more on this later) is displayed.

Expiration  –
MaximumAge defines how often ClickOnce should check for updates for an Application. ClickOnce keeps track of the last time the update check took place for the application. On application launch if CurrentTime – LastCheckForUpdateTime > MaximumAge, a thread is fired up to perform the update check in the background. Note the check is non blocking and the Application launch is not blocked. If an update is detected (Updated deployment manifest version) a property is set in the clickonce store indicating that an update for the app is available. Next time when the app is launched from the Desktop shortcut the Update Confirmation dialog is displayed.

The UpdateConfirmationDialog –
There are three user actions possible::

1. Clicking Ok
Clicking OK on the Dialog downloads the Updated Application and launches it.
The detected update is considered a Required Update if the <minimumRequiredVersion> set on the updated deployment is greater than the version the user has installed locally on the machine. For required updates no UpdateConfirmationDialog is displayed i.e. The user is not provided with an option to skip the update, rather is assumed to have clicked “Ok” on the dialog.

2. Clicking Skip
Clicking on Skip launches the locally installed version of the application AND makes sure you are not prompted for that particular update for a week.

To reitterate, clicking on Skip is equivalent to “Do not prompt me for this particular update for a week”. The week time limit is non configurable.
Note that you will no be “Prompted” for a week – however clickonce will still check for updates based on you maxAge or beforeApplicationStartup setting. If it detects a newer Update (You skipped V2, however now V3 is available) you will be prompted for the new update.

3. Closing the Dialog (Clicking on X)
Closing the dialog launches the locally installed copy of the application – However it does NOT set the “No prompt for a week” setting. So the next time you try to launch the application you are reprompted for the same update.

NOTE – By design if your application would like tighter control of its update lifecycle it can opt out of Clickonce updates by having an empty <subscription> tag. It can then use the ApplicationDeployment Update APIs for update management.
(Unfortunately a bug in Beta2 causes an empty/missing <subscription> section to cause the APIs to throw an exception saying the App is non updatable – The best workaround is to have a <subscription> section with a real high value for <maxAge>)

NOTE – Clicking on a URI to the .application directly always gives you the latest copy on the server independent of the update logic above.


Comments (6)

  1. praveen says:

    this is great stuff saurabh, thanks!

  2. Manoj Amin says:

    thanks saurabh for insight of clickonce. i am wondering if microsoft is going to address the bug you have mentioned, about not being able to use ApplicationDeployment Update APIs with an empty <subscription> tag.

  3. Saurabh says:

    Manoj the issue has been fixed in the VS 2005 official release.

  4. adam says:

    can you have users change the subscription tag at runtime

  5. Saurabh says:

    The manifest are signed and should not be modified at runtime. If you need control of the you apps update the ApplicationDeployment APIs are the way to go …


  6. Saurabh says:

    Munirul (ClickOnce Dev) just brought it to my attention that the  syntax I have above for the <subscription> tag is wrong. Below is the correct syntax …