Install Clickonce Programmatically Open
Install ClickOnce application programmatically (C#) Skip to content. All gists; GitHub; Sign up for a GitHub account Sign in. Using Github windows desktop, the local code of the PDF tool is synchronised with the Github repository. The ClickOnce equivalent is conditional download groups - but MAGE -FromDirectory does not support building conditional download groups. Another ClickOnce disappointment. But at least this one has workarounds. ClickOnce applications do a great job of isolating applications from each other. This was done for two reasons, security and maintainability. Firstly, it allows for greater security since the.NET Framework manages security via code access policies. Secondly, it increases maintainability by preventing the problems with 'DLL hell'.
With the .NET 4.0 Framework, Microsoft has added the ability to turn on verbose logging for the install, update, and uninstall of a ClickOnce application. Of course, it doesn’t do much good to modify the amount of logging without providing access to the log file, so they have also added the ability to let you specify the location and name of the output file for the logging. When you define the log file path, it creates or appends to the log file every time a ClickOnce application is installed, updated, or uninstalled. It even works if you are doing programmatic updates.
What’s particularly keen about these features is that they work for any ClickOnce application as long as .NET 4.0 is installed. In other words, if your ClickOnce application targets the .NET 2.0, 3.0, or 3.5 Framework, you can still install the .NET 4.0 Framework on the computer and take advantage of the new logging features. (Installing .NET 4.0 also installs the updated ClickOnce engine, which is more stable.)
Now what you really want to know is what the log files look like, so you’ll know whether this is worth the trouble. I created a small application that has one Windows Form, and I deployed it with ClickOnce. I installed and uninstalled it with verbose logging turned on and with verbose logging turned off. Then I added programmatic updates and let it update asynchronously and restart the application. The logging for automatic updates is the same as an install, but it’s less detailed if you are using programmatic updates. Here are the log files:
ClickOnceLog_Verbose_Install
ClickOnceLog_Verbose_Uninstall
ClickOnceLog_Verbose_Update_Programmatic
ClickOnceLog_NotVerbose_Install
ClickOnceLog_NotVerbose_Uninstall
Zip file of all five log files
Since you’re still reading this, you probably want to know how to turn on the verbose logging and set up the log file. Or at least, how to set up the log file (you may think the verbose logging is too chatty). It’s very simple. You need to add some entries to the Windows registry.
Install Clickonce Programmatically Open Files
The log file path goes here:
HKEY_Current_UserSoftwareClassesSoftwareMicrosoftWindowsCurrentVersionDeploymentLogFilePath
The registry key for verbose logging goes here:
HKEY_Current_UserSoftwareClassesSoftwareMicrosoftWindowsCurrentVersionDeploymentLogVerbosityLevel
To add these, open the registry editor and drill down to the Deployment sub-key. Right-click on Deployment and select “New” and then “String Value” as displayed here:
Type in the key name and press Enter. Then press Enter again or double-click on the entry to set the value.
Type in the value and press Enter.
If you want to stop outputting the logging, delete the registry key for the LogFilePath.
If you change or set the LogFilePath, it takes effect immediately. If you change or set the LogVerbosityLevel, it does not take effect until the user logs off and logs back in.
Another fun piece of information: If you set the LogFilePath to an empty string instead of deleting the registry entry, every time you run the ClickOnce application, you will get an error that dfsvc.exe (the ClickOnce service) is no longer working. (I’m thinking that’s not a feature.)
One word of caution: there is no automatic cleanup of the log file, no rollover when it gets to a certain size or anything like that. ClickOnce continues to append to the log file with every install, update, and uninstall. So if you start up the logging on someone’s computer, you must remember to come back around and turn it back off.
If you want to leave the logging turned on, I strongly recommend that you have your application manage the log file. For example, you could rename the log file every time a new one is created, and make sure you only keep the most recent one. You can tell if the application is newly installed or if an update is newly installed by checking the IsNetworkDeployed property of System.Deployment.Application.ApplicationDeployment. If true, the user just installed the application, or installed an update, and you could manage the log file at that time.
Programmatically modifying the registry
Editing the registry is fraught with peril. I remember the old days when you used to be able to call Microsoft for help with Windows (the REALLY old days). One of the first things they would ask you was, “Did you edit the Windows registry?” It only took one phone call to learn that if you said “Yes”, they would not help you. This taught many developers to, well, lie.
So just for grins, I wrote a small .NET application that provides a user interface you can use to change the registry entries for the ClickOnce logging. Basically it displays a screen where you can browse to the folder where you want your log files, and you can turn verbose logging on and off. Here’s what the UI looks like:
You could take this project and set the target Framework to the same as your application. If your user has the .NET Framework installed on their computer, you can just build this application and then copy the executable to the user’s machine and run it to set the values. Or better yet, put it on a thumb drive and run the executable from there.
Since the registry entries are in HKCU, you could also have your ClickOnce application update these values, but that’s not helpful for the first install!
Let’s take a look at the LogSettings class that does all the work. This is in C#, but the whole solution is available in both C# and VB at the end of this article.
First, here are the namespaces you need to include. Microsoft.Win32 is for the registry changes.
Next are the constants and properties. This includes the registry sub-key name. When you retrieve the registry sub-key, you specify which hive, such as HKCU, so it is not part of the sub-key name.
Here is the method called to create an instance of the class; this reads the current entries from the registry and stores them in the class properties. First you open the sub-key, and then you retrieve the two values that you need.
And last, but not least, here is the method to save the entries back to the registry. You open the sub-key in write mode, so you can modify the associated values. If the log level is not set to verbose, this deletes the value for the logging level from the registry. If no file name is specified for the log file, this deletes that registry entry. Otherwise, the entries are updated with the values set on the screen.
The Visual Studio 2010 solutions can be downloaded in either CSharp or VB.
Acknowledgements
Thanks very much to Jason Salameh at Microsoft, who I believe was largely responsible for adding this feature. I believe it will provide some clarity and help with troubleshooting when people have problems installing ClickOnce applications.
[Edit 7/7/2011 Move downloads to Azure blob storage]
[Edit 3/8/2014 Move to different Azure blob storage]
Tags: ClickOnce
I set my ClickOnce application to not checking for updates (Project Properties -> Publish -> Updates... -> 'The application should check for updates' is unchecked) since I programmatically search for them and I leave the user the possibility to install them whenever he wants.
Now in the following scenario:
- The application is launched
- An update is found using the ClickOnce API
- The application is not updated
- The application is then closed
- The next time the application is launched the ClickOnce window will prompt the user to install or skip the update.
How can this be avoided?
Interestingly, if then the user skip the installation, the next times the application will be launched the user will not be prompted any more, hence there should be something (in the manifest?) that tells ClickOnce to stop prompting.
Bronumski2 Answers
I have seen something like this before. I think what is happening is that when the application is start up ClickOnce does not check for an update, which is what you have set. When you are run the application an update check is done programatically and an update is found and presumably a flag is set. The application is then shutdown with out updating but the flag is still set. The next time the application is started ClickOnce still does not check for an update BUT because there is a flag set that there is an update available it prompts the user to see if they want to grab the update. I am guessing that this is by design.
In regards to the second point where you skip the update you will not be prompted again until there is another update. This I believe is by design, if you want to go back and do the update you need to go to the ClickOnce install page for the application.
Ideally what you want to be able to do is do the same thing that happens when you skip using the ClickOnce dialog programatically using the Application Deployment API. I have had a quick look at the public methods available but I cannot see anything about skipping but maybe you can find something.
EDIT
Just had another look at the API. Are you calling CheckForUpdate() or CheckForDetailedUpdate() without a boolean parameter? If so the reason you are getting the prompt is as I said the update check is being stored:
If CheckForUpdate discovers that an update is available, and the user chooses not to install it, ClickOnce will prompt the user that an update is available the next time the application is run. There is no way to disable this prompting. (If the application is a required update, ClickOnce will install it without prompting.)
Instead you want to call the method you are using with a boolean value of false, the boolean flag determines if a dialog should be displayed to the user.
persistUpdateCheckResult Type: System.Boolean If false, the update will be applied silently and no dialog box will be displayed.
BronumskiBronumskiI see that the ApplicationDeployment.CheckForUpdate() method has an overload with persistUpdateCheckResult
parameter.
However I am using the CheckForUpdateAsync
which does not have any such overload. It appears to imply the persistence of the result as I am running into this issue.
I guess the solution is I write my own async call...
sll