JPReddy
JPReddy

Reputation: 65503

ClickOnce update cancelled by user and it never asks for an update again

I've a Windows Forms application, and it is deployed through ClickOnce. During launch of the application it checks for an update and prompts the user for the same. If the user choose not to install the update for that session, it doesn't ask anymore. Is this by design or am I missing any setting?

How do I make it prompt the user for an update next time he launches the application?

Upvotes: 14

Views: 11085

Answers (3)

Jan Köhler
Jan Köhler

Reputation: 6030

I have found another solution than waiting a week. However, this solution is generally not applicable for normal users. For me as a developer (local admin on my PC), however, it is.

I had accidentally skipped the update. As I said, however, I didn't want to wait a week. Inspired by this StackOverflow answer, I realised that ClickOnce applications save the skipping in the registry. My solution is to manipulate the marker that recognizes that the user has skipped the update.

The relevant ClickOnce info gets stored to this registry location: Computer\HKEY_CLASSES_ROOT\Software\Microsoft\Windows\CurrentVersion\Deployment\SideBySide\2.0\PackageMetadata\{2ec93463-b0c3-45e1-8364-327e96aea856}_{3f471841-eef2-47d6-89c0-d028f03a4ad5} Although this path seems quite dynamic/individual with all those GUIDs it's rather static and constant in all cases.

The tricky part is now to find the right subdirectory for your own case. There seem to be two directories for each ClickOnce application. In the directory with the shortest suffix there is a registry entry with the key {2ad613da-6fdb-4671-af9e-18ab2e4df4d8}!UpdateSkipTime. Yep, the GUID is constant again...

If you skipped the update, the key's value is the timestamp when the skip occured. Now by setting this value to lower value, one can make the update-dialog appear again. I did this using this powershell script:

$packageMetadataEntry = "HKEY_CLASSES_ROOT\Software\Microsoft\Windows\CurrentVersion\Deployment\SideBySide\2.0\PackageMetadata\{2ec93463-b0c3-45e1-8364-327e96aea856}_{3f471841-eef2-47d6-89c0-d028f03a4ad5}\"
$appEntry = "foo..bar_0000000000000000_d0653325c3f06cf6"
$registryPath = $packageMetadataEntry + $appEntry
$valueName = "{2ad613da-6fdb-4671-af9e-18ab2e4df4d8}!UpdateSkipTime"
$binaryData = [system.Text.Encoding]::Unicode.GetBytes("0001/01/01 00:00:00`0") # has to be terminated with a null byte (`0)

[Microsoft.Win32.Registry]::SetValue($registryPath, $valueName, $binaryData, [Microsoft.Win32.RegistryValueKind]::Binary)

⚠️ Disclaimer: Better backup that registry entry before any manipulation! 😉

Upvotes: 0

Richard Dunlap
Richard Dunlap

Reputation: 1957

Another alternative is to implement programmatic ClickOnce updates where you can define the behavior yourself. I suspect it's using a blunderbuss as a flyswatter in this case, but if you want to consider the option, one starting point is MSDN - Check for Application Updates Programmatically Using the ClickOnce Deployment API.

Upvotes: 4

Justin
Justin

Reputation: 6711

When the user clicks "Skip", it means "Ask me again in 1 week". There is no way to adjust this time delay.

If you release a new version of the application in the meantime, the user will again be prompted to update.

You can also prevent the user from skipping the update in the first place by:

  • Checking for updates before the application starts, and
  • Making the update required by specifying a minimum version

In this case, the user must either update or they cannot run the program. See MSDN - Choosing a ClickOnce Update Strategy for details.

Upvotes: 26

Related Questions