如何使应用程序设置独立于.exe路径



假设我想将我的应用程序从c:\myapp.exe移动到d:\myapp.exe。它将丢失所有设置。如何防止这种情况发生?

就我个人而言,我使用注册表来保存和加载我的设置,所以我的应用程序的位置不会受到影响,但如果您使用User。配置etc并希望修复位置,这可能会有所帮助:我可以控制的位置吗。NET用户设置以避免在应用程序升级时丢失设置?

它是LocalFileSettingsProvider类的实现细节。它的任务是将用户范围的设置存储在一个文件中,该文件保证是唯一的,这样不同的应用程序就不会意外地覆盖其他设置。

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

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

因此,不可避免的是,如果你把.exe移到其他地方,就会改变哈希,这会让你得到一个空的user.config文件,所有设置都恢复到默认设置。

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

    -

这100%取决于应用程序。

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

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

如果您安装了该应用程序,它也存储在注册表中,从"添加/删除"程序卸载将不再有效。

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

希望它能帮助你的事业…:)

您可以创建自己的Settings类。它的工作原理和原作一样。下面我发布了设置类的实现。如有任何改进,我们将不胜感激。

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。

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

最新更新