如何在.net中的不同程序集版本之间保留user.config设置?


146

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

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

当我们使用Clickonce时,它似乎可以处理,因此似乎应该可以完成,但我不确定如何处理。



不,这是指默认情况下不将文件检入版本控制中(或因此收集),这是针对最终用户的(Windows)用户特定设置
Davy8,2009年

我只需要这个问题,谢谢:)
Binary Worrier 2010年

我在以下线程中发布了一种可能的解决方案:stackoverflow.com/a/47921377/3223783希望能对您有所帮助!
dontbyteme

我已经在这个线程中发布了一个可能的解决方案。希望有帮助!
dontbyteme

Answers:


236

ApplicationSettingsBase具有一种名为Upgrade方法,该方法可迁移先前版本中的所有设置。

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

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

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

MSDN上了解有关升级方法的更多信息。该GetPreviousVersion也可能是值得一试,如果你需要做一些定制的合并。


2
一个小问题,什么构成一个新版本?4个零件号的任何部分?我使用ClickOnce,那是另外一种动物吗?
折射圣骑士

4
UpgradeRequired应该是哪种类型的设置?appSettingsuserSettingsapplicationSettings?作为Settings.Settings上的用户设置,第一次将其更改为false时,它将永远不再为true。新版本不会将UpgradeRequired重置为True。
Dialex'Apr 29'15

4
@dialex必须是用户设置。应用程序类型的设置为只读。新版本号确实会导致设置重置,因为设置存储在特定于版本的路径中。
伦纳德·锡

4
我想我回答了我自己的问题。如果存在以前版本的设置文件,则每次应用启动时,它将其值复制到最新版本中,可能不是您想要的!
休·杰夫纳

1
令我惊讶的是,这不仅是默认行为。如果应用程序的设置在启动时为空,并且找到了前一组设置,则将其加载。
SteveCinq

3

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


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发表有关此问题的出色文章。您可以在此处阅读有关它的更多详细信息。


1

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

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

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();

0

如果您以编程方式对user.settings进行了更改,那么如何在单独的文件(例如user.customized.settings)中保留(只是)对user.settings所做的修改的副本?

您可能仍然还希望维护并在user.settings中加载修改后的设置。但是通过这种方式,当您使用新版本的user.settings安装较新版本的应用程序时,可以通过将用户复制回新的user.settings来询问用户是否要继续使用其修改后的设置。您可以批发进口它们,也可以求婚,要求用户确认要继续使用哪些设置。

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


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();
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.