假设我想将我的应用程序从 c:\myapp.exe 移动到 d:\myapp.exe。它将失去所有设置。如何防止这种情况?
5 回答
我个人使用注册表来保存和加载我的设置,因此我的应用程序的位置不受影响,但是如果您使用 User.Config 等并想要修复该位置,这可能会有所帮助: 我可以控制.NET 用户设置以避免丢失应用程序升级设置?
它是 LocalFileSettingsProvider 类的实现细节。它具有将用户范围的设置存储在保证是唯一的文件中的令人羡慕的工作,这样不同的应用程序就不会意外地覆盖彼此的设置。
它通过将文件存储在具有散列名称的 AppData 目录中来实现这一点。哈希是根据应用程序的几个属性计算的。它尽可能多地抓取,从 AssemblyInfo.cs 文件中的属性开始。特别是 [AssemblyVersion] 很重要,它可以检测到您的应用程序的新版本可能与 user.config 文件的旧版本不兼容。
但属性不足以使其唯一,它还在哈希中使用 .exe 的完整路径名。对于适当的 .config 文件,这是一个非常强大的选择器。
因此,不可避免地,如果您将 .exe 移动到其他地方,这将改变哈希值,这将使您获得一个空的 user.config 文件,其中所有设置都恢复为默认设置。
修补这个有点可疑,一个应用程序应该只有一个安装目录。c:\program files\companyname\appname 是标准。但是您可以通过实现自己的 SettingsProvider 类。这并不容易做到,System.Configuration 是一个非常讨厌的命名空间。但是一个不错的起点是RegistrySettingsProvider 示例,它可能可以按原样使用。
-
-
这 100% 取决于应用程序。
应用程序本身只需要找到它的依赖项,或者它需要运行的 DLL 列表。大多数时候它会在当前目录中查找这些内容,因此这通常不是问题。
最大的问题是在注册表中。如果应用程序已将其安装位置写入注册表,它可能会在运行时在旧目录中查找某些文件。
如果您安装了该应用程序,它也会存储在注册表中,并且从添加/删除程序中卸载将不再起作用。
但是,如果应用程序不使用注册表,则可以将其移动而不会产生任何后果。许多使用闪存驱动器的便携式应用程序采用这种方法,因此可以根据需要移动或删除......
希望它对您的事业有所帮助..:)
您可以创建自己的设置类。它的工作原理与原版一样。下面我发布我的设置类的实现。任何改进将不胜感激。
using System;
using System.ComponentModel;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using Microsoft.Win32;
namespace MyNamespace
{
static class Settings
{
private static string _connectionString = @"data source=C:\\database.s3db";
public static string ConnectionString
{
get { return GetSetting("_connectionString"); }
set { _connectionString = value; }
}
private static string _archives = "";
public static string Archives
{
get { return GetSetting("_archives"); }
set { _archives = value; }
}
public static bool CheckDuplicates
{
get { return bool.Parse(GetSetting("_checkDuplicates")); }
set { _checkDuplicates = value; }
}
private static bool _saveDocks = true;
public static bool SaveDocks
{
get { return bool.Parse(GetSetting("_saveDocks")); }
set { _saveDocks = value; }
}
private static Font _font = new Font("Tahoma", 12, GraphicsUnit.Pixel);
public static Font Font
{
get
{
var convert = new FontConverter();
var value = convert.ConvertFromString(GetSetting("_font"));
return (Font) value;
}
set { _font = value; }
}
public static void Save()
{
Type type = typeof(Settings);
var registryKey = Registry.CurrentUser.CreateSubKey(string.Format(@"Software\{0}\{1}\Settings", Application.CompanyName, Application.ProductName));
if (registryKey != null)
{
foreach (var field in type.GetFields(BindingFlags.NonPublic | BindingFlags.Static))
{
var converter = TypeDescriptor.GetConverter(field.FieldType);
var value = converter.ConvertToString(field.GetValue(null));
registryKey.SetValue(field.Name, value ?? field.GetValue(null));
}
registryKey.Close();
}
}
public static void SetDefaults()
{
var registryKey = Registry.CurrentUser.OpenSubKey(string.Format(@"Software\{0}\{1}\Settings", Application.CompanyName, Application.ProductName));
if (registryKey == null)
{
Save();
}
else
{
registryKey = Registry.CurrentUser.CreateSubKey(string.Format(@"Software\{0}\{1}\Settings", Application.CompanyName, Application.ProductName));
if(registryKey == null) return;
Type type = typeof(Settings);
foreach (var field in type.GetFields(BindingFlags.NonPublic | BindingFlags.Static))
{
if (registryKey.GetValue(field.Name) != null)
{
var converter = TypeDescriptor.GetConverter(field.FieldType);
var value = converter.ConvertFrom(registryKey.GetValue(field.Name, field.GetValue(null)));
field.SetValue(null, value);
}
}
registryKey.Close();
}
}
private static string GetSetting(string name)
{
var registryKey = Registry.CurrentUser.OpenSubKey(string.Format(@"Software\{0}\{1}\Settings", Application.CompanyName, Application.ProductName));
if (registryKey != null)
{
if (registryKey.GetValue(name) != null)
{
return registryKey.GetValue(name).ToString();
}
registryKey.Close();
}
return "";
}
}
}
要在您的应用程序中使用它,只需像上面一样为您的设置添加属性和支持字段。确保在属性的 get 访问器的 GetSetting 方法中使用支持字段的名称作为字符串参数。确保为设置字段分配默认值。
有关保存设置,请参见下面的代码。
Settings.Archives = ".7z,.rar,.zip";
Settings.CheckDuplicates = true;
Settings.SaveDocks = false;
Settings.Font = fontDialog.Font;
Settings.Save();
您必须在主窗体的构造函数中调用 SetDefaults 方法。请参见下面的代码。
namespace MyNamespace
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
Settings.SetDefaults();
}
}
}
如果你有改进这门课的建议。然后发表评论。
制作一个单独的 dll 以通过您喜欢的任何方法读取设置 - 注册表或 xml 读取,......并将其放入系统路径中。然后你可以在你的exe所在的任何地方调用dll。
但是什么情况下需要这个要求呢?我只是好奇。