2010-01-21 4 views
3

У меня есть приложение WinForms, которое развертывается с использованием системы публикации Visual Studio 2008 (ClickOnce). В app.config файл приложения У меня есть раздел конфигурации, который требуется компонентом третьей стороной, которая имеет вид:Изменение конфигурационных разделов в App.config во время выполнения или времени установки

<section name="thirdPartySection" 
type="System.Configuration.NameValueSectionHandler" /> 

раздел является, таким образом, не в AppSettings и выглядит как:

<thirdPartySection > 
    <add key="someKey" value="someValue" /> 
</thirdPartySection > 

I что пары ключ/значение являются NameValueCollection. Проблема я лицо, что я хочу изменения значения либо время развертывания или во время выполнения (либо это хорошо со мной), так что someValue будет someOtherValue на основе среды, установленной в.

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

Кто-нибудь знает, что лучший вариант для изменения этих данных? Изменение времени выполнения с помощью ConfigurationManager.RefreshSection() будет больше соответствовать моему текущему коду, но я также открыт для предложений на этапе установки.

Редактировать: Это работает во время выполнения. Вот как я справлялся со старыми конфигурационными переопределениями.

Configuration config = ConfigurationManager.OpenExeConfiguration(
    ConfigurationUserLevel.None); 

config.AppSettings.Settings["Main.ConnectionString"].Value = 
    PolicyTrackerInfo.ConnectionString; 

config.AppSettings.Settings["Main.linq"].Value = 
    PolicyTrackerInfo.LinqConnectionString; 


config.Save(ConfigurationSaveMode.Modified); 

ConfigurationManager.RefreshSection("appSettings"); 

Моя попытка сделать то же самое для другого раздела:

string overwriteXml = config.GetSection("thirdPartySection") 
    .SectionInformation.GetRawXml(); 

XmlDocument xml = new XmlDocument(); 
xml.LoadXml(overwriteXml); 
XmlNode node = xml.SelectSingleNode("thirdPartySection/add"); 
node.Attributes["value"].Value = PolicyTrackerInfo.OverwriteString; 

До сих пор, так хорошо. Однако я не вижу метода, который позволяет мне заменить старый XML на мои измененные данные. Возможно ли это во время выполнения?

В стороне: я попытался изменить файл app.config.deploy вручную. Это просто дает мне ошибку проверки, так как модификация обнаружена установщиком, и она отказывается продолжать. Мне очень нравится автоматическое развертывание, и предыдущее переопределение работало отлично.

ответ

1

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

<thirdPartySection> 
    <add key="someKey" value="#NEEDS_INITIALIZED#" /> 
</thirdPartySection > 

И ваш метод Main может выглядеть примерно так:

static public void Main(params string[] args) 
{ 
    const string uninitializedValue = "#NEEDS_INITIALIZED#"; 

    // Load the third-party config section (this assumes it inherits from 
    // ConfigurationElementCollection 
    var config = ConfigurationManager.OpenExeConfiguration(
     ConfigurationUserLevel.None); 
    var section = config.GetSection("thirdPartySection") 
     as NameValueConfigurationCollection; 
    var setting = section["someKey"]; 
    if (setting.Value == uninitializedValue) 
    { 
     setting.Value = PolicyTrackerInfo.OverwriteString; 
     config.Save(); 
    } 
} 
+0

Я пробовал использовать «как NameValueConfigurationCollection», но мне сказали, что он не может преобразовать раздел в такую ​​коллекцию. Я видел много сообщений, рекомендующих этот подход: есть ли что-то, что нужно зарегистрировать или иным образом настроить для использования? Он выглядит простой методикой, поэтому я считаю, что это очень полезно (и ваш подход к тестированию для конфигурации, поэтому он выполняется только один раз, вероятно, это то, что я должен был сделать, но перезапись выполнялась, и поэтому она осталась там). – Godeke

+0

System.Configuration должно быть все, что вам нужно в качестве ссылки. Проблема может заключаться в том, что сторонняя секция не выводится из NameValueConfigurationCollection. В строке, где вы получите раздел, можете ли вы проверить его в отладчике, чтобы узнать, какой он тип? – Jacob

+0

Я принял ваш ответ, чтобы получить награду. Если я не пытаюсь использовать этот раздел, это просто «ConfigurationSection», как и ожидалось. Если я отлаживаю это System.Config.DefaultSection (несмотря на форматирование данных в разделе, соответствующем разделу NameValue). – Godeke

0

Я бы написал custom installer и в событии AfterInstall изменил конфигурационный файл с использованием механизмов XML, которые вы указали выше. Однако я не знаю, как это работает с ClickOnce.

+0

Проблема у меня есть с пользовательской программой установки, я потерять главную особенность Click Однажды: если я обновляю код и развертываю его, все пользователи * принудительно * немедленно обновляют (это находится в корпоративной среде). Потеря этого (и простота ClickOnce, что мне нравится) означает, помимо написания установщика, я должен написать автообновление, которое обнаруживает, что код устарел и обеспечивает некоторый простой механизм обновления. Учитывая, насколько легко обновлять другие разделы app.config, мне трудно поверить, что это опция * best *. – Godeke

+0

Это говорит о том, что, поскольку никто не выходил на все * в первые 4 дня этой награды, я предполагаю, что обновление app.config либо сложнее, чем я думал, либо мне не удалось использовать Stack Overflow правильно в некотором роде. – Godeke

+0

Я думаю, что вы все еще можете установить с помощью ClickOnce, предполагая, что вы поддерживаете автономный режим, и чтобы пользовательский класс установки еще выполнялся. Тогда вам не нужно ничего делать, кроме того, что уже поддерживает ClickOnce. –

1

Ради выдвигая идею, что люди могут голосовать вверх или вниз (не то, что я видел многое другое, чем перекати вокруг этого вопроса), я имею в виду, используя технику размещены здесь: http://www.devx.com/dotnet/Article/10045

Основная идея состоит в том, чтобы сделать ClickOnce развернуть приложение для прокладки, которое просто сделает XCOPY-развертывание основного приложения (и поскольку оно не использует файл app.config, я могу просто использовать стандартные методы модификации XML и делать с ним).

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