如果我将已编译的应用程序重命名为myapp.exe
到app.exe
,那么当我运行重命名的可执行文件时,会在此路径中生成一个新的用户设置文件夹:
C:\Users\{User}\AppData\Local\{CompanyName}\{ExecutableName}_Url_{SystemGUID or something strange}
所以我放弃了所有已保存的设置。
然后我如何解决在VBNET
WinForms
我自己的位置定义存储user.config
文件或使用应用程序设置基础结构的任何其他解决方案的问题? (不保存注册表或其他内容的设置)
答案 0 :(得分:7)
我想您也可以使用ConfigurationManager.OpenExeConfiguration方法从特定位置打开配置文件。
希望我帮忙!
答案 1 :(得分:6)
更多信息以及回答您问题的链接中的花絮:
您引用的“systemGUID或其他东西”实际上是2件事的散列(参考MSDN My.Settings):
<eid> is the URL, StrongName, or Path, based on the evidence available to hash.
<hash> is a SHA1 hash of evidence gathered from the CurrentDomain,
in the following order of preference:
- StrongName
- URL If neither of these is available, use the .exe path.
如果没有StrongName,您的位置会因路径而异,这是您描述的问题。由于BOTH eid和hash将使用StrongName作为哈希值,因此即使将其移动到其他位置或安装新版本,完整路径仍应保持不变。使用StrongName时,凭据来自应用程序,并且哈希值不会更改,并且永远不会使用最后的方法(exe路径)。这回答了你的基本问题:使用强名称,路径不会改变。
新版本/版本将在该文件夹下为“设置”的每个版本创建一个子文件夹树。链接中提到的Upgrade
Settings
方法(显然)有助于从/之前的版本导入设置。 EXE名称的更改将导致AppDomain.FriendlyName(第3个元素)发生更改。
隔离存储是另一种选择,它并不像它第一次看起来那么难,但具有类似的行为。使用Iso,您不需要指定文件夹,因为它只在Users\<User>\Isolated Storage\zhxytg\dhfyres\
这样一个不起眼的位置创建一个文件夹。如果您使用ClickOnce(即,这是另一种可行的解决方案),即使您重命名,所以应用程序的所有版本的位置CAN都保持不变。
我认为您必须使用ClickOnce(StrongName作为MSDN中的替代品)来获取应用程序级别证据。作为附带的好处,使用ISO,即使在最高安全性下,非管理员用户也可以读取/写入ProgramData\AllUsers
中的共享文件(可能是许可证的情况,或应用程序套件的共享设置)与W7。应用程序的哈希允许它写入该路径,因此它可以做一些我们通常无法做的事情。
如果您不使用ClickOnce,您仍然可以获得一个稳定的文件夹每次安装并读取/写入AllUsers
。新安装(到不同的文件夹)将导致不同的散列和文件位置;与更改文件名相同。即使您设法将旧位置存储在某处,新安装也可能没有旧文件的权限(没有尝试过)。
ISO删除因EXEName而异,但它不使用My.Settings。而是使用由IsolatedFileStreams
个对象创建的IsolatedStorageFile
。而且你必须接管组织和管理各种设置的值和名称。使用的隔离存储类型(应用/用户)取决于可用的凭据。
隔离存储有它的位置,但似乎对设置来说太过分了。
您提到您通常只使用MySettings来处理琐碎的应用程序。因此,仅仅为了稳定设置路径而使用StrongName似乎有点矫枉过正。 ISO非常有趣,但有一些更简单的东西。第三个选项属于您不想要的or other things
,但非常灵活。
围绕序列化构建自己的设置类。对于简单设置,这些可能不仅仅是一组Name-Value Pairs {LastPath =“.....”; FormLeft = x; FormTop = y ...}。将它们保存在Dictionary(Of String, String)
或Dictionary(Of enumSettings, String)
中,然后序列化(保存)整个容器:
Dim bf As New BinaryFormatter
Using fs As New FileStream(myFile, FileMode.OpenOrCreate)
bf.Serialize(fs, _UserOpts)
End Using
获取价值同样简单。对于需要保存许多类型的更复杂项目,如Integer,Date,Array,ArrayList,List(of T)等,为它们创建一个UserOptions类,并序列化那个。
请注意,您将文件流传递给序列化程序,因此您可以完全控制名称和位置,例如C:\Users\<username>\AppData\Local\<Company>\<Product>\Settings.bin
位置不会因版本,文化,程序集等而改变。它将保留在您放置它的位置
当您尝试对点类型,大小和字体等类型进行血清化时,这确实会耗尽,因为对象无法直接序列化。特别是,使用ProtoBuff有多种选择可以将这些转换为可动态或事先可序列化的东西。