Can I control the location of .NET user settings to avoid losing settings on application upgrade?

.Net 2.0Settings

.Net 2.0 Problem Overview


I'm trying to customize the location of the user.config file. Currently it's stored with a hash and version number

%AppData%\[CompanyName]\[ExeName]_Url_[some_hash]\[Version]\

I want to it be agnostic to the version of the application

%AppData%\[CompanyName]\[ProductName]\

Can this be done and how? What are the implications? Will the user lose their settings from the previous version after upgrading?

.Net 2.0 Solutions


Solution 1 - .Net 2.0

I wanted to add this quoted text as a reference for when i have this problem in the future. Supposedly you can instruct the ApplicationSettings infrastructure to copy settings from a previous version by calling Upgrade:

Properties.Settings.Value.Upgrade();

From Client Settings FAQ blog post: (archive)

> Q: Why is there a version number in the user.config path? If I deploy a new version of my application, won't the user lose all the settings saved by the previous version? > > A: There are couple of reasons why the > user.config path is version sensitive. > > (1) To support side-by-side deployment > of different versions of an > application (you can do this with > Clickonce, for example). It is > possible for different version of the > application to have different settings > saved out. > > (2) When you upgrade an > application, the settings class may > have been altered and may not be > compatible with what's saved out, > which can lead to problems. > > However, we have made it easy to > upgrade settings from a previous > version of the application to the > latest. Simply call > ApplicationSettingsBase.Upgrade() and > it will retrieve settings from the > previous version that match the > current version of the class and store > them out in the current version's > user.config file. You also have the > option of overriding this behavior > either in your settings class or in > your provider implementation. > > Q: Okay, but how do I know when to > call Upgrade? > > A: Good question. In Clickonce, when > you install a new version of your > application, ApplicationSettingsBase > will detect it and automatically > upgrade settings for you at the point > settings are loaded. In non-Clickonce > cases, there is no automatic upgrade - > you have to call Upgrade yourself. > Here is one idea for determining when > to call Upgrade: > > Have a boolean setting called > CallUpgrade and give it a default > value of true. When your app starts > up, you can do something like: >

if (Properties.Settings.Value.CallUpgrade)
{
   Properties.Settings.Value.Upgrade();
   Properties.Settings.Value.CallUpgrade = false;    
}

> > This will ensure that Upgrade() is > called only the first time the > application runs after a new version > is deployed.

i don't believe for a second that it could actually work - there's no way Microsoft would provide this ability, but the method is there just the same.

Solution 2 - .Net 2.0

To answer the first question, you technically can put the file wherever you want, however you will have to code it yourself, as the default place the file goes to is the first of your two examples. (link to how to do it yourself)

As for the second question, it depends on how you deploy the application. If you deploy via a .msi, then there are two hashes in the properties of the setup project (that the msi is built from), the 'upgrade code' and the 'product code'. These determine how the msi can be installed, and if it upgrades, overwrites, or installs beside any other version of the same application.

For instance, if you have two versions of your software and they have different 'upgrade' codes, then to windows they are completely different pieces of software regardless of what the name is. However if the 'upgrade' code is the same, but the 'product' code is different then when you try to install the 2nd msi it will ask you if you want to upgrade, at which time it is supposed to copy the values from the old config to a new config. If both values are the same, and the version number didn't change then the new config will be in the same location as the old config, and it won't have to do anything. MSDN Documentation

ClickOnce is a little bit different, because its based more off of the ClickOnce version # and URL path, however I have found that as long as you continue to 'Publish' to the same location the new version of the application will continue to use the existing config. (link to how ClickOnce handles updates)

I also know there is a way to manually merge configs during the install of the msi using custom install scripts, but I don't remember the exact steps to do it... (see this link for how to do it with a web.config)

Solution 3 - .Net 2.0

The user.config file is stored at

c:\Documents and Settings>\<username>\[Local Settings\]Application Data\<companyname>\<appdomainname>_<eid>_<hash>\<verison>

<c:\Documents and Settings> is the user data directory, either non-roaming (Local Settings above) or roaming.
<username> is the user name.
<companyname> is the CompanyNameAttribute value, if available. Otherwise, ignore this element.
<appdomainname> is the AppDomain.CurrentDomain.FriendlyName. This usually defaults to the .exe name.
<eid> is the URL, StrongName, or Path, based on the evidence available to hash.
<hash> is a SHA1 hash of evidence gathered from the CurrentDomain, in the following order of preference:
1. StrongName
2. URL:
If neither of these is available, use the .exe path.
<version> is the AssemblyInfo's AssemblyVersionAttribute setting.

Full description is here <http://msdn.microsoft.com/en-us/library/ms379611.aspx>

Solution 4 - .Net 2.0

(I'd add this as a comment to @Amr's answer, but I don't have enough rep to do that yet.)

The info in the MSDN article is very clear and appears to still apply. However it fails to mention that the SHA1 hash is written out base 32 encoded, rather than the more typical base 16.

I believe the algorithm being used is implemented in ToBase32StringSuitableForDirName, which can be found here in the Microsoft Reference Source.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMuxaView Question on Stackoverflow
Solution 1 - .Net 2.0Ian BoydView Answer on Stackoverflow
Solution 2 - .Net 2.0uzbonesView Answer on Stackoverflow
Solution 3 - .Net 2.0AmrView Answer on Stackoverflow
Solution 4 - .Net 2.0JulianRendellView Answer on Stackoverflow