Сделать строку постоянной в приложении .NET - PullRequest
7 голосов
/ 11 мая 2019

Я пытаюсь сделать строку постоянной в приложении .NET, написанном на C ++ под VS 2008 (а именно, это путь к файлу).Мне просто нужно прочитать его при запуске приложения и написать при выходе.

Я изо всех сил пытаюсь найти правильный способ сделать это.Поиск в Интернете направил меня к объектам ConfigurationSettings и ConfigurationManager.Похоже, что первое доступно только для чтения, а второе не найдено в справочнике по конфигурации (framework 3.5).

Я знаю, что могу выполнять явные операции чтения / записи в реестр или внешние файлы, ноЯ бы предпочел более стандартный способ.Я не ожидаю, что для этого потребуется более двух строк кода.

Я на правильном пути?

Ответы [ 3 ]

3 голосов
/ 21 мая 2019

В VS2008 и .NET Framework 3.5 вы не можете создать манифест, необходимый для изменения app.config, если приложение установлено в подпапке% ProgramFiles% или% ProgramFiles (x86)%, поскольку они специально защищены ОС, и вы не можете записать в HKLM-узел реестра, не будучи повышенным процессом.

Я думаю, что я бы закодировал значение по умолчанию и логическое значение, указывающее, работает ли приложение в переносном режиме, в app.config. Считайте значение по умолчанию из app.config, перезаписайте переменную значением из user.config (если оно существует) и запишите значение в user.config, если в переносном режиме, и в app.config, если в непереносимом режиме.

В пользовательских классах, независимо от того, какая плохая поддержка исходит от фреймворка (нет доступа на запись в app.config, нет гибридного режима) ...

app.config:

<? Xml version = "1.0" encoding = "utf-8"?>





<добавить key = "PortableMode" value = "Off" />
<добавить key = "SomethingPath" value = "Программное обеспечение \ Cragin \ FooApp \ SomethingPath" />

Я думаю, что это больше, чем 250 строк кода, а не 2, но это помогает (извините, это на C #, но вы, вероятно, знаете, как адаптировать его к C ++).

using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml.Linq;

namespace DesktopApp1 {

    static class Program {

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
            Config myConfig = new Config();
            myConfig.Load();

            //Change settings during the livetime of the application
            myConfig.SomethingPath = @"C:\Temp\Foo\TestUser.dat";
            myConfig.PortableMode = false;

            //Write it when closing the application
            myConfig.Save();

        }

    }

    internal class Config {

        //Private Fields
        private AppOrUserConfig _Config;
        private Boolean _IsUserConfig;
        private String _AppConfigPath;
        private String _UserConfigPath;

        public void Load() {
            AppOrUserConfig myDefaultConfig = new AppOrUserConfig();
            AppOrUserConfig myAppConfig = new AppOrUserConfig(AppConfigPath, myDefaultConfig);
            if (myAppConfig.PortableMode) {
                _Config = myAppConfig;
                _IsUserConfig = false;
            } else {
                _Config = new AppOrUserConfig(UserConfigPath, myAppConfig);
                _IsUserConfig = true;
            }
        }

        public Boolean Save() {
            CheckLoad();
            String myFilePath = IsUserConfig ? UserConfigPath : AppConfigPath;
            try {
                String myContent = _Config.XmlContent;
                String myFolder = Path.GetDirectoryName(myFilePath);
                Directory.CreateDirectory(myFolder);
                File.Delete(myFilePath);
                File.WriteAllText(myFilePath, myContent, new UTF8Encoding(true));
                return true;
            } catch {
            }
            return false;
        }

        public Boolean PortableMode {
            get {
                CheckLoad();
                return _Config.PortableMode;
            }
            set {
                CheckLoad();
                if (PortableMode == value) return;
                if (value) {
                    _Config.PortableMode = true;
                    _IsUserConfig = false;
                    Save();
                } else {
                    String myPath = SomethingPath;
                    _Config.PortableMode = false;
                    Save();
                    Load();
                    SomethingPath = myPath;
                }
            }
        }

        public String SomethingPath {
            get {
                CheckLoad();
                return _Config.SomethingPath;
            }
            set {
                CheckLoad();
                _Config.SomethingPath = value;
            }
        }

        private String AppConfigPath {
            get {
                String myResult = _AppConfigPath;
                if (myResult == null) {
                    myResult = Assembly.GetEntryAssembly().EntryPoint.DeclaringType.Module.FullyQualifiedName + ".config";
                    _AppConfigPath = myResult;
                }
                return myResult;
            }
        }

        private String UserConfigPath {
            get {
                String myResult = _UserConfigPath;
                if (myResult == null) {
                    myResult = Path.Combine(Environment.ExpandEnvironmentVariables(@"%LOCALAPPDATA%\Cragin\FooApp"), Path.GetFileName(AppConfigPath));
                    _UserConfigPath = myResult;
                }
                return myResult;
            }
        }

        private Boolean IsUserConfig {
            get {
                return _IsUserConfig;
            }
        }

        private void CheckLoad() {
            if (_Config == null) throw new InvalidOperationException(@"Call method ""Load()"" first.");
        }

    }

    internal class AppOrUserConfig {

        //Private Fields
        private XDocument _Xml;

        //Constructors

        public AppOrUserConfig() {
            _Xml = XDocument.Parse(@"<?xml version=""1.0"" encoding=""utf-8""?>
                                        <configuration>
                                        <startup>
                                            <supportedRuntime version=""v2.0.50727""/>
                                        </startup>
                                        <appSettings>
                                            <add key=""PortableMode"" value=""Off""/>
                                            <add key=""SomethingPath"" value=""C:\ProgramData\Cragin\SomeLibrary""/>
                                        </appSettings>
                                        </configuration>");
        }

        public AppOrUserConfig(String filePath, AppOrUserConfig defaultValue) : this() {
            XDocument myXml = null;
            try {
                myXml = XDocument.Parse(File.ReadAllText(filePath));
            } catch {
                return;
            }
            AppOrUserConfig myDummy = new AppOrUserConfig(myXml, defaultValue);
            PortableMode = myDummy.PortableMode;
            SomethingPath = myDummy.SomethingPath;
        }

        public AppOrUserConfig(XDocument xml, AppOrUserConfig defaultValue) : this() {
            if (defaultValue == null) defaultValue = new AppOrUserConfig();
            if (xml == null) {
                PortableMode = defaultValue.PortableMode;
                SomethingPath = defaultValue.SomethingPath;
                return;
            }
            AppOrUserConfig myDummy = new AppOrUserConfig();
            myDummy._Xml = xml;
            PortableMode = myDummy.GetPortableMode(defaultValue.PortableMode);
            SomethingPath = myDummy.GetSomethingPath(defaultValue.SomethingPath);
        }

        public Boolean PortableMode {
            get {
                return GetPortableMode(false);
            }
            set {
                (from e in _Xml.Element("configuration").Element("appSettings").Elements("add") where (string)e.Attribute("key") == "PortableMode" select e).Last().Attribute("value").Value = value ? "on" : "off";
            }
        }

        public String SomethingPath {
            get {
                return GetSomethingPath(@"C:\ProgramData\Cragin\SomeLibrary");
            }
            set {
                (from e in _Xml.Element("configuration").Element("appSettings").Elements("add") where (string)e.Attribute("key") == "SomethingPath" select e).Last().Attribute("value").Value = value ?? "";
            }
        }

        public String XmlContent {
            get {
                return _Xml.ToString(SaveOptions.None);
            }
        }

        private Boolean GetPortableMode(Boolean defaultValue) {
            try {
                String myString = (from e in _Xml.Element("configuration").Element("appSettings").Elements("add") where (string)e.Attribute("key") == "PortableMode" select e).Last().Attribute("value").Value;
                return ToBoolean(myString);
            } catch {
                PortableMode = defaultValue;
                return defaultValue;
            }
        }

        private String GetSomethingPath(String defaultValue) {
            try {
                return (from e in _Xml.Element("configuration").Element("appSettings").Elements("add") where (string)e.Attribute("key") == "SomethingPath" select e).Last().Attribute("value").Value;
            } catch {
                SomethingPath = defaultValue;
                return defaultValue;
            }
        }

        private static Boolean ToBoolean(String value) {
            value = value.Trim();
            switch (value.Length) {
                case 1:
                    if (value[0] == '0') return false;
                    if (value[0] == '1') return true;
                    break;
                case 5:
                    if (value.ToLowerInvariant() == "false") return false;
                    break;
                case 4:
                    if (value.ToLowerInvariant() == "true") return true;
                    break;
                case 3:
                    if (value.ToLowerInvariant() == "off") return false;
                    break;
                case 2:
                    if (value.ToLowerInvariant() == "on") return true;
                    break;
            }
            throw new FormatException();
        }

    }

}

Надеюсь, это пригодится вам или кому-то еще.

1 голос
/ 16 мая 2019

Я решил это сам с помощью ConfigurationManager, вдохновленного этим примером: https://docs.microsoft.com/en-us/dotnet/api/system.configuration.appsettingssection?view=netframework-4.8

Моя реализация работает, но я ее не понимаю.

0 голосов
/ 17 мая 2019

Возможно, вы захотите использовать Изолированное хранилище :

Для настольных приложений изолированное хранилище - это механизм хранения данных, обеспечивающий изоляцию и безопасность путем определения стандартизированных способов.связывания кода с сохраненными данными.Стандартизация предоставляет и другие преимущества.Администраторы могут использовать инструменты, предназначенные для управления изолированным хранилищем, для настройки пространства хранения файлов, установки политик безопасности и удаления неиспользуемых данных.Благодаря изолированному хранилищу вашему коду больше не нужны уникальные пути для указания безопасных расположений в файловой системе, а данные защищены от других приложений, которые имеют доступ только к изолированному хранилищу.Жестко запрограммированная информация, указывающая, где находится область хранения приложения, не нужна.

Как указано выше, вам не нужно беспокоиться о возможных различиях на разных машинах или о создании собственного решения.это может быть хрупким.

Ваше решение, хотя оно и может работать, кажется, что оно относится к этой "проприетарной" категории и, возможно, не лучшим образом использует диспетчер конфигурации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...