我可以控制 .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>

&lt;c:\Documents and Settings&gt; 是用户数据目录,可以是非漫游(上述本地设置)或漫游。&lt;username&gt; 是用户名。&lt;companyname&gt; 是 CompanyNameAttribute 值(如果可用)。否则,忽略此元素。&lt;appdomainname&gt; 是 AppDomain.CurrentDomain.FriendlyName。这通常默认为 .exe 名称。&lt;eid&gt; 是 URL、StrongName 或路径,基于可用于散列的证据。&lt;hash&gt; 是从 CurrentDomain 收集的证据的 SHA1 散列,在以下优先顺序: 1. 强名 2. 网址: 如果这些都不可用,请使用 .exe 路径。&lt;version&gt; 是 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 用户设置的位置以避免在应用程序升级时丢失设置吗?的主要内容,如果未能解决你的问题,请参考以下文章

谷歌地图 WatchPosition 无法正常工作

怎么解决远程桌面背景是黑色的?

测量调用 ASP.NET MVC 控制器操作的时间

移动 Hibernate 工具以构建时间

如何在后台运行 android 服务 24x7 以获取用户的位置

安卓应用的用户设置活动