160

基本上问题是每次程序集版本更改(即用户安装应用程序的新版本)时,他们的所有设置都会重置为默认值(或者更准确地说,在具有不同版本的文件夹中创建新的 user.config 文件数字作为名称)

升级版本时如何保持相同的设置,因为似乎不鼓励使用 ini 文件或注册表?

当我们使用 Clickonce 时,它​​似乎能够处理这个问题,所以它似乎应该能够完成,但我不确定如何。

4

7 回答 7

262

ApplicationSettingsBase 有一个名为 Upgrade 的方法,它可以迁移以前版本的所有设置。

为了在您发布应用程序的新版本时运行合并,您可以在设置文件中定义一个默认为 true 的布尔标志。将其命名为UpgradeRequired或类似名称。

然后,在应用程序启动时,您检查是否设置了标志,如果是,则调用Upgrade 方法,将标志设置为 false 并保存您的配置。

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

在MSDN上阅读有关升级方法的更多信息。如果您需要进行一些自定义合并,GetPreviousVersion也可能值得一看。

于 2009-02-10T21:41:25.623 回答
6

当我们每个版本只需要升级一次时,下一个简短的解决方案对我有用。它不需要额外的设置,例如UpgradeRequired

if (!ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).HasFile)
    Settings.Default.Upgrade();
于 2020-11-20T08:52:00.373 回答
4

我知道已经有一段时间了......在winforms应用程序中,只需My.Settings.Upgrade()在加载它们之前调用。这将获得最新的设置,无论是当前版本还是以前的版本。

于 2016-03-13T01:01:01.190 回答
2

这是我的研究,以防其他人在迁移已更改/删除的设置时遇到困难。基本问题是,GetPreviousVersion()如果您在新版本的应用程序中重命名或删除了设置,这将不起作用。因此,您需要将设置保留在您的Settings类中,但添加一些属性/工件,这样您就不会无意中在其他地方的代码中使用它,使其过时。VB.NET 中的示例过时设置如下所示(可以轻松转换为 C#):

<UserScopedSetting(),
DebuggerNonUserCode(),
DefaultSettingValue(""),
Obsolete("Do not use this property for any purpose. Use YOUR_NEW_SETTING_NAME instead."),
NoSettingsVersionUpgrade()>
Public Property OldSettingName() As String
  Get
    Throw New NotSupportedException("This property is obsolete")
  End Get
  Set
    Throw New NotSupportedException("This property is obsolete")
  End Set
End Property

确保将此属性添加到具有应用程序设置的同一名称空间/类中。在 VB.NET 中,这个类被命名MySettings并且在My命名空间中可用。您可以使用部分类功能来防止过时的设置与当前设置混淆。

完全归功于 jsharrison 发表了一篇关于这个问题的优秀文章。您可以在此处阅读有关它的更多详细信息。

于 2016-04-13T15:48:33.313 回答
1

这是此处介绍的解决方案的一种变体,它将升级逻辑封装到设置类可以从中派生的抽象类中。

一些建议的解决方案使用 DefaultSettingsValue 属性来指定一个值,该值指示何时未加载先前的设置。我的偏好是简单地使用默认值表明这一点的类型。作为奖励,日期时间?是有用的调试信息。

public abstract class UserSettingsBase : ApplicationSettingsBase
{
    public UserSettingsBase() : base()
    {
        // Accessing a property attempts to load the settings for this assembly version
        // If LastSaved has no value (default) an upgrade might be needed
        if (LastSaved == null)
        {
            Upgrade();
        }
    }

    [UserScopedSetting]
    public DateTime? LastSaved
    {
        get { return (DateTime?)this[nameof(LastSaved)]; }
        private set { this[nameof(LastSaved)] = value; }
    }

    public override void Save()
    {
        LastSaved = DateTime.Now;
        base.Save();
    }
}

派生自 UserSettingsBase:

public class MySettings : UserSettingsBase
{
    [UserScopedSetting]
    public string SomeSetting
    {
        get { return (string)this[nameof(SomeSetting)]; }
        set { this[nameof(SomeSetting)] = value; }
    }

    public MySettings() : base() { }
}

并使用它:

// Existing settings are loaded and upgraded if needed
MySettings settings = new MySettings();
...
settings.SomeSetting = "SomeValue";
...
settings.Save();
于 2018-01-21T07:06:38.173 回答
0

如果您对 user.settings 的更改是以编程方式完成的,那么如何在单独的文件(例如 user.customized.settings)中维护(仅)对 user.settings 的修改的副本?

您可能还想在 user.settings 中维护和加载修改后的设置。但是这样,当您使用更新版本的 user.settings 安装应用程序的更新版本时,您可以通过将修改后的设置复制回新的 user.settings 来询问用户是否要继续使用修改后的设置。您可以批量导入它们,或者更高级地要求用户确认他们想要继续使用哪些设置。

编辑:我在“更准确”的部分上读得太快了关于程序集版本导致新的 user.settings 安装到新版本特定的目录中。因此,上面的想法可能对您没有帮助,但可能会提供一些思考。

于 2009-02-10T21:42:10.163 回答
0

我是这样处理的:

public virtual void LoadSettings(ServiceFileFormBaseSettings settings = null, bool resetSettingsToDefaults = false)
{
    if (settings == null)
            return;

    if (resetSettingsToDefaults)
        settings.Reset();
    else
    {
        settings.Reload();

        if (settings.IsDefault)
            settings.Upgrade();
    }

    this.Size = settings.FormSize;

}

在设置类中,我定义了 IsDefault 属性:

// SaveSettings always sets this to be FALSE.
// This will have the default value TRUE when first deployed, or immediately after an upgrade.
// When the settings exist, this is false.
//
[UserScopedSettingAttribute()]
[DefaultSettingValueAttribute("true")]
public virtual bool IsDefault
{
    get { return (bool)this["IsDefault"]; }
    set { this["IsDefault"] = value; }
}

在 SaveSettings 中,我将 IsDefault 设置为 false:

public virtual void SaveSettings(ServiceFileFormBaseSettings settings = null)
{
    if (settings == null) // ignore calls from this base form, if any
        return;

    settings.IsDefault = false;
    settings.FormSize = this.Size;
    settings.Save();
}
于 2015-05-11T15:46:33.010 回答