Изменение App.config во время выполнения - PullRequest
7 голосов
/ 05 января 2010

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

Вот сцена: приложение WinForms предназначено для тестирования WebApp, разделенного на 5 подсистем. Процесс тестирования работает с сообщениями, отправляемыми между подсистемами, и для успешного выполнения этого процесса каждая подсистема должна иметь свой собственный файл .config.

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

Я знаю, что определение проблемы может быть немного запутанным, но я был бы очень признателен, если бы кто-то помог мне.

Заранее спасибо!

--- ОБНОВЛЕНИЕ 01-06-10 ---

Есть кое-что, что я не упомянул раньше. Первоначально наша система представляет собой веб-приложение с вызовами WCF между каждой подсистемой. По причинам тестирования производительности (мы используем ANTS 4) нам пришлось создать локальную копию сборок и ссылаться на них из тестового проекта. Возможно, это звучит немного неправильно, но мы не смогли найти удовлетворительный способ измерения производительности удаленного приложения.

--- Конец обновления ---

Вот что я делаю:

public void UpdateAppSettings(string key, string value)
{
    XmlDocument xmlDoc = XmlDocument.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);

    foreach (XmlElement item in xmlDoc.DocumentElement)
    {
        foreach (XmlNode node in item.ChildNodes)
        {
            if (node.Name == key)
            {
                node.Attributes[0].Value = value;
                break;
            }
        }
    }

    xmlDoc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);

    System.Configuration.ConfigurationManager.RefreshSection("section/subSection");    
}

Ответы [ 4 ]

25 голосов
/ 11 апреля 2012

Я понимаю, что это довольно старая тема, но я не смог заставить перечисленные методы работать. Вот более простая версия метода UpdateAppSettings (с использованием .NET 4.0):

private void UpdateAppSettings(string theKey, string theValue)
        {
            Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            if (ConfigurationManager.AppSettings.AllKeys.Contains(theKey))
            {
                configuration.AppSettings.Settings[theKey].Value = theValue;
            }

            configuration.Save(ConfigurationSaveMode.Modified);

            ConfigurationManager.RefreshSection("appSettings");
        }

Довольно читабельно и не требует обхода app.config с использованием Xpath или чего-либо подобного. Примечание. Приведенный выше код взят из этого фрагмента в MSDN.

3 голосов
/ 06 января 2010

UPDATE

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

Решение показано здесь. http://web -beta.archive.org / веб / 20150107004558 / www.devnewsgroups.net / группа / microsoft.public.dotnet.xml / topic40736.aspx


Старые вещи ниже

Попробуйте это:

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

Важным моментом является утверждение using, которое будет dispose(), которое, как мне кажется, было вашей проблемой.

Дайте мне знать, удачи.

  public void UpdateAppSettings(string key, string value)
  {
    using (XmlDocument xmlDoc = new XmlDocument())
    {
      xmlDoc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
      xmlDoc.DocumentElement.FirstChild.SelectSingleNode("descendant::"+key).Attributes[0].Value = value;
      xmlDoc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
    }
    System.Configuration.ConfigurationManager.RefreshSection("section/subSection");
  }
1 голос
/ 05 января 2010

Полагаю, вы не закрываете дескриптор файла в первый раз, поэтому Windows не "видит", что вы делаете последующие изменения.

Я предлагаю использовать API-вызов IIS и отключитьвеб-приложение (и пул), внесите изменения, включите веб-приложение.Таким образом, вы уверены, что он будет перечитывать файл и иметь «чистую» среду для каждого теста.

0 голосов
/ 05 января 2010

Предполагая, что дескриптор файла для файла конфигурации закрывается после того, как файл конфигурации был прочитан и обработан, я отправил бы сообщение приложению, чтобы сказать ему перечитать файл конфигурации после того, как вы обновите файл. Если этот подход не работает, то я подозреваю (как предположил Хоган), что дескриптор файла не закрыт. Какие коды ошибок вы получаете при открытии, чтении и закрытии системных вызовов? (используйте perror для сообщения об ошибке)

...