105

我正在尝试自定义user.config文件的位置。目前它与哈希和版本号一起存储

%AppData%\[CompanyName]\[ExeName]_Url_[some_hash]\[Version]\

我希望它与应用程序的版本无关

%AppData%\[CompanyName]\[ProductName]\

这可以做到吗?怎么做?有什么影响?升级后用户会丢失以前版本的设置吗?

4

4 回答 4

82

我想添加此引用的文本作为将来遇到此问题时的参考。假设您可以通过调用Upgrade指示 ApplicationSettings 基础结构从以前的版本复制设置:

Properties.Settings.Value.Upgrade();

来自客户端设置常见问题解答博客文章:(存档

Q:为什么user.config路径中有版本号?如果我部署新版本的应用程序,用户不会丢失之前版本保存的所有设置吗?

答:user.config 路径对版本敏感的原因有两个。

(1) 支持应用程序不同版本的并行部署(例如,您可以使用 Clickonce 来做到这一点)。不同版本的应用程序可以保存不同的设置。

(2) 升级应用程序时,设置类可能已更改,可能与保存的内容不兼容,这可能会导致问题。

但是,我们可以轻松地将设置从应用程序的早期版本升级到最新版本。只需调用 ApplicationSettingsBase.Upgrade(),它就会从先前版本中检索与当前版本的类匹配的设置,并将它们存储在当前版本的 user.config 文件中。您还可以选择在设置类或提供程序实现中覆盖此行为。

问:好的,但我怎么知道何时调用升级?

答:好问题。在 Clickonce 中,当您安装应用程序的新版本时,ApplicationSettingsBase 会检测到它并在加载设置时自动为您升级设置。在非 Clickonce 的情况下,没有自动升级 - 您必须自己调用升级。这是确定何时调用升级的一种方法:

有一个名为 CallUpgrade 的布尔设置,并给它一个默认值 true。当您的应用启动时,您可以执行以下操作:

if (Properties.Settings.Value.CallUpgrade)
{
   Properties.Settings.Value.Upgrade();
   Properties.Settings.Value.CallUpgrade = false;    
}

这将确保仅在部署新版本后应用程序第一次运行时调用 Upgrade()。

我根本不相信它真的可以工作——微软不可能提供这种能力,但方法是一样的。

于 2009-12-18T12:50:51.077 回答
39

要回答第一个问题,从技术上讲,您可以将文件放在您想要的任何位置,但是您必须自己编写代码,因为文件的默认位置是您的两个示例中的第一个。(链接到如何自己做

至于第二个问题,这取决于你如何部署应用程序。如果您通过 .msi 进行部署,则安装项目(构建 msi)的属性中有两个哈希值,即“升级代码”和“产品代码”。这些决定了如何安装 msi,以及它是否升级、覆盖或安装在同一应用程序的任何其他版本旁边。

例如,如果您有两个版本的软件并且它们具有不同的“升级”代码,那么对于 Windows,无论名称是什么,它们都是完全不同的软件。但是,如果“升级”代码相同,但“产品”代码不同,那么当您尝试安装第二个 msi 时,它会询问您是否要升级,此时它应该从旧配置到新配置。如果两个值相同,并且版本号没有更改,那么新配置将与旧配置位于同一位置,并且不需要执行任何操作。 MSDN 文档

ClickOnce 有点不同,因为它更多地基于 ClickOnce 版本号和 URL 路径,但是我发现只要您继续“发布”到同一位置,新版本的应用程序将继续使用现有配置。(链接到 ClickOnce 如何处理更新

我也知道有一种方法可以在安装 msi 期间使用自定义安装脚本手动合并配置,但我不记得执行此操作的确切步骤...(有关如何使用 web.xml 执行此操作的链接,请参阅链接。配置)

于 2009-03-07T04:40:00.663 回答
33

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. StrongName
2. URL:
如果这些都不可用,请使用 .exe 路径。
<version>是 AssemblyInfo 的 AssemblyVersionAttribute 设置。

完整的描述在这里http://msdn.microsoft.com/en-us/library/ms379611.aspx

于 2009-03-07T04:18:31.403 回答
5

(我会将此作为评论添加到@Amr 的答案中,但我还没有足够的代表来做到这一点。)

MSDN 文章中的信息非常清楚,似乎仍然适用。然而,它没有提到 SHA1 散列是用 base 32 编码的,而不是更典型的 base 16。

我相信正在使用的算法是在 中实现的ToBase32StringSuitableForDirName可以在 Microsoft 参考源中找到

于 2014-10-21T18:46:45.823 回答