基本上问题是每次程序集版本更改(即用户安装新版本的应用程序)时,所有设置都会重置默认值(或者更准确地说,在一个文件夹中创建一个新的user.config文件一个不同的版本号作为名称)
升级版本时如何保持相同的设置,因为似乎不鼓励使用ini文件或注册表?
当我们使用Clickonce时,它似乎能够处理这个问题,所以它似乎应该可以完成,但我不确定如何。
答案 0 :(得分:213)
ApplicationSettingsBase有一个method called Upgrade,用于迁移先前版本的所有设置。
为了在发布应用程序的新版本时运行合并,您可以在设置文件中定义一个默认为true的布尔标志。将其命名为 UpgradeRequired 或类似名称。
然后,在应用程序启动时,检查标志是否已设置,如果是,请调用Upgrade method,将标志设置为false并保存配置。
if (Settings.Default.UpgradeRequired)
{
Settings.Default.Upgrade();
Settings.Default.UpgradeRequired = false;
Settings.Default.Save();
}
在MSDN了解有关升级方法的详情。如果您需要进行一些自定义合并,GetPreviousVersion也可能值得一看。
答案 1 :(得分:1)
我知道它已经有一段时间了......
在winforms应用中,只需在加载前调用My.Settings.Upgrade()
即可。这将获得最新设置,无论是当前版本还是先前版本。
答案 2 :(得分:1)
以下是我的研究,以防其他任何人在迁移已更改/删除的设置时遇到困难。基本问题是,如果您在新版本的应用程序中重命名或删除了该设置,则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对此问题发布excellent article完全赞同。你可以在那里阅读更多相关细节。
答案 3 :(得分: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();
答案 4 :(得分:1)
当我们每个版本只需要升级一次时,下一个简短的解决方案对我有用。它确实不需要其他设置,例如UpgradeRequired
:
if (!ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).HasFile)
Settings.Default.Upgrade();
答案 5 :(得分:0)
如果以编程方式完成对user.settings的更改,那么如何在单独的文件中维护(仅)对user.settings的修改的副本,例如: user.customized.settings?
您可能仍希望在user.settings中维护和加载修改后的设置。但是,当您使用较新版本的user.settings安装较新版本的应用程序时,您可以询问用户是否要继续使用修改后的设置,将其复制回新的user.settings。您可以批量导入它们,或者获得更好的功能,并要求用户确认他们想继续使用哪些设置。
编辑:我在关于汇编版本的“更准确”部分上读得太快,导致新的用户设置被安装到新版本特定的目录中。因此,上述想法可能对您没有帮助,但可能会提供一些思考的食物。
答案 6 :(得分: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();
}