Alterando o App.config no tempo de execução

Estou escrevendo um aplicativo WinForms / C # / .NET 3.5 de teste para o sistema que estamos desenvolvendo e caímos na necessidade de alternar entre arquivos .config em tempo de execução, mas isso está se tornando um pesadelo.

Aqui está a cena: o aplicativo WinForms tem como objective testar um WebApp, dividido em 5 subsistemas. O processo de teste funciona com mensagens sendo enviadas entre os subsistemas e, para que esse processo seja bem-sucedido, cada subsistema passou a ter seu próprio arquivo .config.

Para o meu aplicativo de teste, eu escrevi 5 arquivos de configuração separados. Eu gostaria de poder alternar entre esses 5 arquivos durante o tempo de execução, mas o problema é: Eu posso editar programaticamente o arquivo .config do aplicativo várias vezes, mas essas mudanças só terão efeito uma vez. Eu tenho procurado há muito tempo por um formulário para resolver esse problema, mas eu ainda não fui bem sucedido.

Eu sei que a definição do problema pode ser um pouco confusa, mas eu realmente aprecio se alguém me ajudar.

Desde já, obrigado!

— ATUALIZAÇÃO 01-06-10 —

Há algo que eu não mencionei antes. Originalmente, nosso sistema é um aplicativo da Web com chamadas do WCF entre cada subsistema. Por motivos de teste de desempenho (estamos usando o ANTS 4), tivemos que criar uma cópia local dos assemblies e referenciá-los a partir do projeto de teste. Pode parecer um pouco errado, mas não conseguimos encontrar uma maneira satisfatória de medir o desempenho de um aplicativo remoto.

— Atualização final —

Veja o que estou fazendo:

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

ATUALIZAR

A solução abaixo não funcionou porque o XmlDocument não descarta e parece que algumas versões do .net não fecham corretamente quando recebem um caminho de arquivo. A solução (código de exemplo no link) é abrir um stream que fará um descarte e passará esse stream para a function de salvamento.

Uma solução é mostrada aqui. http://web-beta.archive.org/web/20150107004558/www.devnewsgroups.net/group/microsoft.public.dotnet.xml/topic40736.aspx


Coisas antigas abaixo

Tente isto:

Note, eu mudei para xpath, mas já faz um tempo, então eu poderia ter errado o xpath, mas em qualquer caso você deveria usar xpath e não andar na tree. Como você pode ver, é muito mais claro.

O ponto importante é a declaração using que irá dispose() , o que eu acho que foi o seu problema.

Deixe-me saber, boa sorte.

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

Eu entendo este é um segmento bastante antigo, mas eu não consegui obter os methods listados para trabalhar. Aqui está uma versão mais simples do método UpdateAppSettings (usando o .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"); } 

Muito legível e evita ter que percorrer o app.config usando Xpath ou algo parecido. Observação: o código acima é inspirado neste snippet no MSDN.

Meu palpite é que você não está realmente fechando o arquivo na primeira vez, então o Windows não “vê” você fazendo as mudanças posteriores.

Minhas sugestões é usar uma chamada de API para o IIS e desativar o aplicativo da web (e o pool), fazer a alteração, ativar o aplicativo da web. Dessa forma, você tem certeza de que irá reler o arquivo e ter um ambiente “limpo” para cada teste.

Supondo que o identificador de arquivo para o arquivo de configuração é fechado após o arquivo de configuração ter sido lido e processado, eu enviaria uma mensagem para o aplicativo para avisá-lo para reler o arquivo de configuração depois de atualizar o arquivo. Se essa abordagem não estiver funcionando, suspeito (como sugeriu Hogan) que o identificador de arquivo não está fechado. Quais códigos de erro você está recebendo da abertura do arquivo, lendo e fechando as chamadas do sistema? (use perror para reportar a mensagem de erro)