Могу ли я изменить [appname] .exe.config без необходимости вручную читать / писать XMl?

Asked
Viewd6003

4

Я создал некоторые настройки в приложении C # с помощью .NET 3.5 и Visual Studio 2008 Express. У меня есть ряд настроек, связанных с приложением, которые я хотел бы изменить из приложения - я могу получить к ним доступ через Properties.Settings.Default, но они читаются только так, как ожидалось. Я не хочу, чтобы они становились пользовательскими настройками, поскольку они должны быть общими для всего приложения. Возможно ли это без загрузки XML и чтения / записи из / в него самостоятельно?

Я видел примеры с использованием System.Configuration.ConfigurationManager.OpenExeConfiguration, но конфигурационный xml выглядит в формате, отличном от того, который я использую (это из более старой версии?)

Спасибо


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

 Configuration config = ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);
SettingElementCollection settingElements = ((ClientSettingsSection)config.GetSectionGroup("applicationSettings").Sections[0]).Settings;

SettingElement element = settingElements.Get("SettingName");
element.Value.ValueXml.InnerText = "new value";

config.Save(ConfigurationSaveMode.Modified, true);
 

6003

2 ответов

1

OpenExeConfiguration (или любой из другие методы ConfigurationManager) является предпочтительной точкой входа для большинства изменений файлов конфигурации. Если у вас есть экземпляр Configuration, вы должны получить раздел, который хотите изменить, и после внесения изменений вызвать любой из ConfigurationManager.Save . Однако получить секцию applicationSettings таким способом невозможно.

В вашем файле applicationSettings нет API для изменения настроек из раздела app.config. Таким образом можно изменить только пользовательские настройки.

Фактически изменить эти настройки можно только путем непосредственного управления XML-файлом app.config.

Может возникнуть некоторая путаница, поскольку индексированное свойство из Properties.Settings.Default действительно доступно для записи. Следующее совершенно законно:

 Properties.Settings.Default["MySetting"] = "New setting value";
Properties.Settings.Default.Save();
 

Однако настройка не будет сохранена.

  • Хм, похоже, он не записывает изменения обратно в файл. Но, может быть, я слишком толстый

    Tom Haigh15 мая 2009, 13:42
  • Окей, кажется, я совершил ошибку, извините за это. После дальнейшего исследования я обнаружил, что вы не можете сохранить настройки области приложения, не прибегая к прямым манипуляциям с xml.

    Ronald Wildenberg16 мая 2009, 10:37
  • Я вижу, что недостаточно хорошо прочитал ваш вопрос. Предлагаемый мной метод предназначен для общих изменений файлов конфигурации. Я обновил свой ответ, чтобы показать еще один (лучший) способ изменения настроек в области сборки.

    Ronald Wildenberg15 мая 2009, 11:55
  • Спасибо. Какой раздел мне понадобится, чтобы получить настройки в Properties.Settings.Default?

    Tom Haigh15 мая 2009, 11:14
  • И не забудьте разрешить разрешения для файла конфигурации. Ожидайте, что файл app.exe.config будет доступен для записи только администраторам.

    Richard15 мая 2009, 10:58
1

Вы также можете использовать реестр Windows для хранения состояния приложения. В реестре есть ключи для каждого пользователя и для каждой машины - вам доступны оба или один из них. Например, некоторые люди используют реестр для хранения местоположения и размера окна приложения при выходе. Затем, когда приложение будет перезапущено, вы можете расположить и изменить размер окна в соответствии с его последним известным размером. Это небольшой пример состояния, которое вы можете сохранить в реестре.

Для этого вы должны использовать разные API для хранения и поиска. В частности, SetValue и GetValue вызывают класс Microsoft.Win32.RegistryKey. Могут быть библиотеки, которые помогают сохранять сложное состояние в реестре. Если у вас есть простые случаи (несколько строк и чисел), то легко сделать это самостоятельно.

   private static string _AppRegyPath = "Software\Vendor Name\Application Name";

  public Microsoft.Win32.RegistryKey AppCuKey
  {
      get
      {
          if (_appCuKey == null)
          {
              _appCuKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(_AppRegyPath, true);
              if (_appCuKey == null)
                  _appCuKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(_AppRegyPath);
          }
          return _appCuKey;
      }
      set { _appCuKey = null; }
  }


  private void RetrieveAndApplyState()
  { 
      string s = (string)AppCuKey.GetValue("textbox1Value");
      if (s != null) this.textbox1.Text = s;

      s = (string)AppCuKey.GetValue("Geometry");
      if (!String.IsNullOrEmpty(s))
      {
          int[] p = Array.ConvertAll<string, int>(s.Split(','),
                           new Converter<string, int>((t) => { return Int32.Parse(t); }));
          if (p != null && p.Length == 4)
          {
              this.Bounds = ConstrainToScreen(new System.Drawing.Rectangle(p[0], p[1], p[2], p[3]));
          }
      }
  }

  private void SaveStateToRegistry()
  {
      AppCuKey.SetValue("textbox1Value", this.textbox1.Text);

      int w = this.Bounds.Width;
      int h = this.Bounds.Height;
      int left = this.Location.X;
      int top = this.Location.Y;

      AppCuKey.SetValue("Geometry", String.Format("{0},{1},{2},{3}", left, top, w, h);
  }


  private System.Drawing.Rectangle ConstrainToScreen(System.Drawing.Rectangle bounds)
  {
      Screen screen = Screen.FromRectangle(bounds);
      System.Drawing.Rectangle workingArea = screen.WorkingArea;
      int width = Math.Min(bounds.Width, workingArea.Width);
      int height = Math.Min(bounds.Height, workingArea.Height);
      // mmm....minimax            
      int left = Math.Min(workingArea.Right - width, Math.Max(bounds.Left, workingArea.Left));
      int top = Math.Min(workingArea.Bottom - height, Math.Max(bounds.Top, workingArea.Top));
      return new System.Drawing.Rectangle(left, top, width, height);
  }
 

В этом коде используется Microsoft.Win32.Registry.CurrentUser, поэтому он устанавливает и извлекает параметры приложения для конкретного пользователя. Если вы устанавливаете или извлекаете общесистемное состояние, вам нужен Microsoft.Win32.Registry.LocalMachine.