Ozzyberto
Ozzyberto

Reputation: 399

Published a ClickOnce application and it keeps resetting its settings

I have deployed this application using Visual Studio 2010's Publish feature; it needs to save a few user settings (such as database connection information) and there is this particular computer that somehow keeps resetting the application's settings. The part that puzzles me the most is that I have not been able to figure out under what circumstances or the reason why this happens. I know the settings are getting set properly because the application has worked just fine on 6 or 7 other computers.

What could be erasing the application's settings? Alternatively, what would you suggest I use to store those settings? An encrypted file?

EDIT: I am using the default application settings. They are defined in the app.config file. They can be accessed using Properties.Settings.Default.propertyName

Upvotes: 12

Views: 8247

Answers (4)

RobinDotNet
RobinDotNet

Reputation: 11877

If you have user-level settings, ClickOnce should copy them forward to the next version's cache when the user gets an update. There are a couple of cases where it doesn't copy the files forward, such as when you change the certificate.

Application-level settings are not retained and carried forward to the next version.

I don't recommend using this mechanism and relying on it. You might want to check out [We rolled our own configuration manager, and store the data as XML and store it. This way, you control what happens to the data.

The only drawback is that when the user uninstalls the app, it leaves this data behind. On the other hand, when the user uninstalls the app, it leaves his data behind, so if he is uninstalling it because he's having a problem, or he clears his ClickOnce cache because he has his problem, then when he installs a new version, his data is still there.

Upvotes: 7

jerha202
jerha202

Reputation: 357

For anyone who runs into this problem: Check if you have an unconditional

Properties.Settings.Default.Upgrade();

in your code. In a ClickOnce installation with multiple versions, this statement copies the user settings from a previous version and overwrites any settings that were saved in the last session. The correct pattern is:

if (Properties.Settings.Default.UpgradeRequired)
{
    Properties.Settings.Default.Upgrade();
    Properties.Settings.Default.UpgradeRequired = false;
    Properties.Settings.Default.Save();
}

where UpgradeRequired is a setting that defaults to true.

Upvotes: 4

Agustin Meriles
Agustin Meriles

Reputation: 4854

I figured a solution that may help future developers with this issue. I realized that, for some reason, the updated version reads some previous configuration settings, but not the last one. For example, if you have this app folders:

myapp_0000000000000000_0001.0000_a4e7e981ca9c18fa
myapp_0000000000000000_0001.0000_a4e7e981ca9c19ee
myapp_0000000000000000_0001.0000_a4e7e981ca9c20aa

when you update, the configuration settings are copied from some random folder different than the last one (I don't know if this is random, probably will take the oldest, but I'm not sure).

So, if you delete the other folders, and left only the last version one, when you update there's no other choice than take the config settings from this only one folder. Try it out for yourself.

So I made this code snippet that runs every time the app starts, that removes the old version folders, so when the next updates came, everything will work fine.

private void ClearOldConfigurations()
{
    var level = ConfigurationUserLevel.PerUserRoamingAndLocal;
    var configuration = ConfigurationManager.OpenExeConfiguration(level);
    var configurationFilePath = configuration.FilePath;

    var routePieces = configurationFilePath.Split(Path.DirectorySeparatorChar);

    var toRetainFolder = string.Empty;
    var toClearFolder = string.Empty;
    for (int i = routePieces.Length - 1; i > 1; i--)
    {
        if (routePieces[i].ToLower() == "data")
        {
            toRetainFolder = string.Join(Path.DirectorySeparatorChar.ToString(), routePieces.Take(i));
            toClearFolder = string.Join(Path.DirectorySeparatorChar.ToString(), routePieces.Take(i - 1));
            break;
        }
    }

    if (string.IsNullOrWhiteSpace(toRetainFolder) || string.IsNullOrWhiteSpace(toClearFolder))
    {
        return;
    }

    foreach (var dir in Directory.GetDirectories(toClearFolder))
    {
        if (dir.ToLower().Trim() != toRetainFolder.ToLower().Trim())
        {
            try
            {
                Directory.Delete(dir, true);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}

Probably not the cleanest solution, but worked for me.

Upvotes: 1

sylvanaar
sylvanaar

Reputation: 8216

It is your job to upgrade the previous settings when you update your application.

Settings.Default.GetPreviousVersion() and Settings.Default.Upgrade() can be helpful for this.

Upvotes: 3

Related Questions