我可以控制 .NET 用户设置的位置以避免在应用程序升级时丢失设置吗?
Posted
技术标签:
【中文标题】我可以控制 .NET 用户设置的位置以避免在应用程序升级时丢失设置吗?【英文标题】:Can I control the location of .NET user settings to avoid losing settings on application upgrade? 【发布时间】:2010-10-11 21:34:19 【问题描述】:我正在尝试自定义user.config
文件的位置。目前它与哈希和版本号一起存储
%AppData%\[CompanyName]\[ExeName]_Url_[some_hash]\[Version]\
我希望它与应用程序的版本无关
%AppData%\[CompanyName]\[ProductName]\
这可以做到吗?如何做到?有什么影响?升级后用户是否会丢失以前版本的设置?
【问题讨论】:
虽然uzbones's 的回答提供了有关文件位置的信息,但我相信Ian's 在升级方面更正确。 @AnthonyMastrean 我个人认为任何重要的设置都不应该依赖于我的 Microsoft 提供的 ApplicationSettings 基础架构。 Muxa 应该只将设置存储在%AppData%\[CompanyName]/[ProductName]
中,我们可以相信它会保留。
毫无疑问,我对内置应用程序和用户设置的持续体验非常糟糕。我推荐 appdata 或 programdata 中的 json 文件。
您还可以将设置存储在注册表中。请参阅***.com/a/12127888/1273550 了解替代设置类的实现。
【参考方案1】:
我想添加这个引用的文本作为将来我遇到此问题时的参考。假设您可以通过调用 Upgrade 来指示 ApplicationSettings 基础架构从以前的版本复制设置:
Properties.Settings.Value.Upgrade();
来自Client Settings FAQ 博文:(archive)
问:为什么 user.config 路径中有版本号?如果我部署新版本的应用程序,用户不会丢失之前版本保存的所有设置吗?
答:有几个原因 user.config 路径是版本敏感的。
(1) 支持并行部署 不同版本的 应用程序(你可以这样做 例如,单击一次)。它是 可能适用于不同版本的 应用程序有不同的设置 救了出来。
(2) 当您升级 应用程序,设置类可以 已被更改,可能不会 与保存的内容兼容, 这可能会导致问题。
但是,我们可以轻松地 从以前的升级设置 应用程序的版本 最新的。只需调用 ApplicationSettingsBase.Upgrade() 和 它将从 以前的版本匹配 类和商店的当前版本 他们在当前版本的 用户配置文件。你也有 覆盖此行为的选项 在您的设置类或 你的提供者实现。
问:好的,但我怎么知道什么时候 呼叫升级?
答:好问题。在 Clickonce 中,当 您安装了新版本的 应用程序,ApplicationSettingsBase 会自动检测到它 为您升级设置 设置已加载。在非 Clickonce 中 情况下,没有自动升级 - 你必须自己打电话升级。 这是确定何时 调用升级:
有一个名为的布尔设置 CallUpgrade 并给它一个默认值 真值。当您的应用启动时 起来,你可以这样做:
if (Properties.Settings.Value.CallUpgrade)
Properties.Settings.Value.Upgrade();
Properties.Settings.Value.CallUpgrade = false;
这将确保 Upgrade() 是 仅第一次调用 应用程序在新版本之后运行 已部署。
我根本不相信它真的可以工作 - 微软不可能提供这种能力,但方法是一样的。
【讨论】:
这完全可行!我只使用了简单的if(CallUpgrade) Upgrade();
语句。
@Ian Boyd:我喜欢这个想法,我对有一个潜在的解决方案感到非常兴奋,但是我对一件事感到困惑。我没有Properties.Settings.Value
我有Properties.Settings
部分,但我是否遗漏了某些内容或者是您特有的?
这个很好用,但是我提醒读者,配置的路径到但不包括版本号必须是相同的。即见@Amr的回答。例如如果应用程序的新版本从与以前版本不同的文件路径启动,则Upgrade
不起作用。
@RefractedPaladin 这是Properties.Settings.Default.Upgrade()
改成false后别忘了加上Properties.Settings.Default.Save();
:-)【参考方案2】:
要回答第一个问题,从技术上讲,您可以将文件放在您想要的任何位置,但是您必须自己编写代码,因为文件的默认位置是您的两个示例中的第一个。 (link to how to do it yourself)
至于第二个问题,这取决于您如何部署应用程序。如果您通过 .msi 进行部署,则安装项目(构建 msi)的属性中有两个哈希值,即“升级代码”和“产品代码”。这些决定了如何安装 msi,以及它是否升级、覆盖或安装在同一应用程序的任何其他版本旁边。
例如,如果您有两个版本的软件并且它们具有不同的“升级”代码,那么对于 Windows,无论名称是什么,它们都是完全不同的软件。但是,如果“升级”代码相同,但“产品”代码不同,那么当您尝试安装第二个 msi 时,它会询问您是否要升级,此时它应该从旧配置到新配置。如果两个值相同,并且版本号没有更改,那么新配置将与旧配置位于同一位置,并且无需执行任何操作。 MSDN Documentation
ClickOnce 有点不同,因为它更多地基于 ClickOnce 版本 # 和 URL 路径,但是我发现只要您继续“发布”到同一位置,新版本的应用程序就会继续使用现有配置。 (link to how ClickOnce handles updates)
我也知道有一种方法可以在安装 msi 期间使用自定义安装脚本手动合并配置,但我不记得执行此操作的确切步骤...(请参阅this 链接了解如何操作它与 web.config)
【讨论】:
升级代码不是应该保持不变的代码,而产品代码不是应该在版本之间更改的代码吗? blogs.msdn.com/b/pusu/archive/2009/06/10/understanding-msi.aspx 噢!你是对的,不敢相信我把它弄反了(花了 2 年时间才赶上它)。这就像在我过去的某个时间点进行机器人签名:( 这是否意味着只有安装用户才能升级她的设置?【参考方案3】:user.config 文件存储在
c:\Documents and Settings>\<username>\[Local Settings\]Application Data\<companyname>\<appdomainname>_<eid>_<hash>\<verison>
<c:\Documents and Settings>
是用户数据目录,可以是非漫游(上述本地设置)或漫游。<username>
是用户名。<companyname>
是 CompanyNameAttribute 值(如果可用)。否则,忽略此元素。<appdomainname>
是 AppDomain.CurrentDomain.FriendlyName。这通常默认为 .exe 名称。<eid>
是 URL、StrongName 或路径,基于可用于散列的证据。<hash>
是从 CurrentDomain 收集的证据的 SHA1 散列,在以下优先顺序:
1. 强名
2. 网址:
如果这些都不可用,请使用 .exe 路径。<version>
是 AssemblyInfo 的 AssemblyVersionAttribute 设置。
完整的描述在这里http://msdn.microsoft.com/en-us/library/ms379611.aspx
【讨论】:
【参考方案4】:(我会将此作为评论添加到@Amr 的答案中,但我还没有足够的代表来做这件事。)
info in the MSDN article 非常明确,似乎仍然适用。但是它没有提到 SHA1 哈希是用 base 32 编码的,而不是更典型的 base 16。
我相信正在使用的算法是在ToBase32StringSuitableForDirName
中实现的,can be found here in the Microsoft Reference Source。
【讨论】:
以上是关于我可以控制 .NET 用户设置的位置以避免在应用程序升级时丢失设置吗?的主要内容,如果未能解决你的问题,请参考以下文章