Правильный способ обновления настроек программы WPF при обновлении программы (Desktop Bridge/Project Centennial)

Когда это была программа clickonce, она работала, но затем я сделал appxpackage и экспортировал его как столетнее приложение для магазина Windows, и обновление больше не работает.

Прямо сейчас у меня в App.xaml.cs

protected override void OnStartup(StartupEventArgs e) {
   if (myprog.Properties.Settings.Default.UpgradeRequired)
   {    
      myprog.Properties.Settings.Default.Upgrade();
      myprog.Properties.Settings.Default.UpgradeRequired = false;
      myprog.Properties.Settings.Default.Save();
   }

С UpgradeRequired как bool в пользовательских настройках. Это правильное место?

Я получаю сброс настроек при каждом обновлении версии. Теперь у меня есть несколько таких каталогов

C:\Users\ я \AppData\Local\progname\prog.exe_Url_randomChars

каждая с несколькими разными версиями настроек программы. Таким образом, после обновления создается еще одна из них, вместо нее вложенная папка с xxxx текущей версии.

Как и раньше, в каждом выпуске версии я увеличиваю версию в информации о сборке, версию сборки, версию файла, и теперь у меня совпадают номера в AppxManifest.xml. Я сохраняю последнюю группу номеров версии 0 в соответствии с рекомендациями и просто увеличиваю третью группу номеров.

Есть что-то, чего мне не хватает?

1 ответ

Приложения UWP и Desktop Bridge должны сохранять свои настройки в ApplicationData.LocalSettings:

https://docs.microsoft.com/en-us/windows/uwp/design/app-settings/store-and-retrieve-app-data

Вы можете загрузить предыдущий файл user.config в текущие настройки. Это просто обходной путь, и его можно использовать для перехода к ApplicationData.LocalSettings.

public static void Init()
{
    if (myprog.Properties.Settings.Default.UpgradeRequired)
    {    
        LoadPreviousSettings(myprog.Properties.Settings.Default);
        myprog.Properties.Settings.Default.UpgradeRequired = false;
        myprog.Properties.Settings.Default.Save();
    }
}

private static void LoadPreviousSettings(params ApplicationSettingsBase[] applicationSettings)
{
    const string companyName = "YOUR_COMPANY_NAME_HERE";
    var userConfigXml = GetUserConfigXml(companyName);
    Configuration config = ConfigurationManager.OpenExeConfiguration(
        ConfigurationUserLevel.PerUserRoamingAndLocal);
    foreach (ApplicationSettingsBase setting in applicationSettings)
    {
        try
        {
            // loads settings from user.config into configuration
            LoadSettingSection(setting, config, userConfigXml);
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("userSettings");
        }
        catch (FileNotFoundException)
        {
            // Could not import settings.
            // Perhaps user has no previous version installed
        }
        setting.Reload();
    }

}

private static void LoadSettingSection(ApplicationSettingsBase setting, Configuration config, XDocument userConfigXml)
{
    string appSettingsXmlName = setting.ToString();
    var settings = userConfigXml.XPathSelectElements("//" + appSettingsXmlName);
    config.GetSectionGroup("userSettings")
        .Sections[appSettingsXmlName]
        .SectionInformation
        .SetRawXml(settings.Single().ToString());
}

private static XDocument GetUserConfigXml(string companyName)
{
    var localPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + $@"\{companyName}";
    // previous package folder
    var previousLocal = GetDirectoryByWriteTime(localPath, 1);
    // previous version, e.g. 1.2.0
    var prevousVersion = GetDirectoryByWriteTime(previousLocal, 0);
    // application settings for previous version
    return XDocument.Load(prevousVersion + @"\user.config");
}

private static string GetDirectoryByWriteTime(string path, int order)
{
    var direcotires = new DirectoryInfo(path).EnumerateDirectories()
        .OrderBy(d => d.LastWriteTime)
        .Reverse()
        .ToList();
    if (direcotires.Count > order)
    {
        var previous = direcotires[order];
        return previous.FullName;
    }
    throw new FileNotFoundException("Previous config file not found.");
}

Здесь есть рабочий ответ.

В основном вам нужно создать дублирующую версию с помощью UWP ApplicationData.Settingsа затем загрузите его в начале приложения. Это очень просто, когда ваши настройки - строки, логические значения и т. Д. Но не так, если у вас есть уникальные настройки.

Чтобы уточнить ответ в ссылке, когда у вас есть настройки, состоящие из пользовательских типов / классов, при создании дублирующей версии UWP вы можете использовать Newtonsoft.Json для сериализации пользовательских настроек:

try
{
    ApplicationData.Current.LocalSettings.Values[value.Name] = value.PropertyValue;
}
catch
{
    string serialised = JsonConvert.SerializeObject(value.PropertyValue);
    ApplicationData.Current.LocalSettings.Values[value.Name] = serialised;
}

Затем при загрузке пользовательской настройки:

if (s.Name == "MyCustomSetting")
{
    var deserialised = JsonConvert.DeserializeObject<MyCustomClass>((string)setting.Value);
    s.PropertyValue = deserialised;
}
Другие вопросы по тегам