Clickonce and startup on windows logon (Vista)

Having issues getting your clickonce applications auto start when logging on to Vista? You have come to the right place! Below is an explanation of various approaches out there and the pros ans cons of each approach and lastly the best working approach!

Solution 1: Placing a shortcut in the startup folder.
One way to fix this problem was to programmatically create a shortcut in the users startup folder.
string publisherName = Application.CompanyName;
string productName = Application.ProductName;
string startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
startupPath = Path.Combine(startupPath, productName) + “.appref-ms”;
if (!File.Exists(startupPath))

{
string allProgramsPath = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
string shortcutPath = Path.Combine(allProgramsPath, publisherName);
shortcutPath = Path.Combine(shortcutPath, productName) + “.appref-ms”;
File.Copy(shortcutPath, startupPath
);

}
Whist this was a good approach but this still has issues.
Issue 1:
Dint work on all windows platforms. Some of my tests failed on one box with Vista Enterprise and strangely worked on another box with Vista Enterprise!

Issue 2:
Uninstalling the application dint remove the shortcut from the startup folder. Thus this would always pop up the installation of the app everytime you login even though you had uninstalled the application.

Solution 2: Creating a url shortcut and placing in the startup folder.
On digging deep in google, I found an approach where you could create “url” shortcuts and place them in the startup folder. Whist this worked reliably on most windows platform, there was a catch!

Issue 1: This approach only works if you are connected to the internet at the time of logging in to windows.

Issue 2:
Uninstalling the application dint remove the shortcut from the startup folder. Thus this would always pop up the installation of the app everytime you login even though you had uninstalled the application.

Solution 3: Using the registry and turning off check for updates (Best approach).
Ok this is the best solution till now as per my experience. This works on all versions of vista where the above two approaches failed.

Just like solution1, you need to create a appref-ms shortcut. But this time it has to be in the current users registry as opposed to the startup folder. Also this requires you to turn off check for updates through clickonce for it to work fully.

Creating the shortcut:
RegistryKey regkey = Registry.CurrentUser.OpenSubKey(“SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run”, true);
string publisherName = Application.CompanyName;
string productName = Application.ProductName;
string allProgramsPath = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
string shortcutPath = Path.Combine(allProgramsPath, publisherName);
shortcutPath = Path.Combine(shortcutPath, productName) + “.appref-ms”;
regkey.DeleteSubKey(“YourApplication”, false);//delete old key if exists
regkey.SetValue(“YourApplication”, shortcutPath);


Once you have this in place, you need to ensure you uncheck the option “Application should check for updates” in the publish properties of your application. This is important. All this means is, you will have to implement code to check for updates when your application starts. This is easy and you can use Application.Deployment namespace to achieve this. Probably fire this “update check” code in your splash screen and force an application.restart if the application was updated. You can make this update process interactive by using Async calls and refreshing you splashscreen with progress bar updates by subscribing to progress events.
Form Load:
ApplicationDeployment.CurrentDeployment.UpdateProgressChanged += new DeploymentProgressChangedEventHandler(UpdateProgress);

Form Shown:
ApplicationDeployment.CurrentDeployment.CheckForUpdateAsync();

private void UpdateProgress(object sender, DeploymentProgressChangedEventArgs e)
{
progressbar1.Value = e.ProgressPercentage;
label1.Text = (e.BytesCompleted / 1024).ToString() + ” of ” + (e.BytesTotal / 1024).ToString() + ” kb downloaded”;
}


After doing this you should be all good to go!

I havent found any issues with this approach till now. Also this approach overcomes the issues with the above two solutions.

Advertisements