【问题标题】:How to make application settings independent of .exe path?如何使应用程序设置独立于 .exe 路径?
【发布时间】:2012-08-14 13:27:28
【问题描述】:

假设我想将我的应用程序从 c:\myapp.exe 移动到 d:\myapp.exe。它将失去所有设置。如何预防?

【问题讨论】:

  • 这是 ProjectProperties -> 设置
  • 如果这些设置保留在与可执行文件一起移动的 app.exe.config 中,为什么还要放弃这些设置?
  • @WiktorZychla 因为它们被标记为用户设置以允许通过 GUI 进行编辑。

标签: c# .net application-settings


【解决方案1】:

我个人使用注册表来保存和加载我的设置,因此我的应用程序的位置不受影响,但如果您使用 User.Config 等并希望修复该位置,这可能会有所帮助: Can I control the location of .NET user settings to avoid losing settings on application upgrade?

【讨论】:

  • 冲浪管家是绝对正确的。使用注册表来保存您的设置是个好主意。您可以使用此技术保存当前用户和本地计算机的设置。
【解决方案2】:

它是 LocalFileSettingsProvider 类的一个实现细节。它具有将用户范围的设置存储在保证唯一的文件中的令人羡慕的工作,这样不同的应用程序就不会意外地覆盖彼此的设置。

它通过将文件存储在具有哈希名称的 AppData 目录中来实现。哈希是根据应用程序的几个属性计算的。它尽可能多地抓取,从 AssemblyInfo.cs 文件中的属性开始。特别是 [AssemblyVersion] 很重要,它可以检测到您的应用程序的新版本可能与 user.config 文件的旧版本不兼容。

但属性不足以使其唯一,它还在哈希中使用 .exe 的完整路径名。对于适当的 .config 文件,这是一个非常强大的选择器。

因此,不可避免地,如果您将 .exe 移动到其他位置,这将改变哈希值,这将使您获得一个空的 user.config 文件,其中所有设置都恢复为默认设置。

修改这个有点问题,一个应用程序应该只有一个安装目录。 c:\program files\companyname\appname 是标准。但是您可以通过实现自己的 SettingsProvider 类。这并不容易做到,System.Configuration 是一个非常讨厌的命名空间。但一个不错的起点是RegistrySettingsProvider sample,它可能可以按原样使用。

    -

【讨论】:

    【解决方案3】:

    这 100% 取决于应用程序。

    应用程序本身只需要找到它的依赖项,或者它需要运行的 DLL 列表。大多数时候它会在当前目录中查找这些内容,因此这通常不是问题。

    最大的问题在于注册表。如果应用程序已将其安装位置写入注册表,它可能会在运行时在旧目录中查找某些文件。

    如果您安装了应用程序,它也会存储在注册表中,并且从添加/删除程序中卸载将不再起作用。

    如果应用程序不使用注册表,则可以移动它而不会产生任何后果。许多使用闪存驱动器的便携式应用程序采用这种方法,因此可以根据需要移动或删除......

    希望它对您的事业有所帮助..:)

    【讨论】:

      【解决方案4】:

      您可以创建自己的设置类。它的工作原理与原版一样。下面我发布我的设置类的实现。任何改进将不胜感激。

      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();
              }
          }
      }
      

      如果您有改进本课程的建议。然后评论。

      【讨论】:

        【解决方案5】:

        制作一个单独的 dll 以通过您喜欢的任何方法读取设置 - 注册表或 xml 读取,...并将其放入系统路径中。然后你可以在你的 exe 所在的任何地方调用 dll。

        但是什么情况下需要这个要求呢?我只是想知道。

        【讨论】:

          猜你喜欢
          • 2017-02-20
          • 2020-03-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-11
          • 1970-01-01
          • 2011-01-30
          • 1970-01-01
          相关资源
          最近更新 更多