开发者

Modifying config sections in App.config either at runtime or install time

开发者 https://www.devze.com 2022-12-17 12:54 出处:网络
I have an WinForms application that is deployed using Visual Studio 2008\'s publish (ClickOnce) system. Within the application\'s app.config file I have a config section that is required by a third pa

I have an WinForms application that is deployed using Visual Studio 2008's publish (ClickOnce) system. Within the application's app.config file I have a config section that is required by a third party component that has the form:

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

The section is thus not in the appSettings and looks like:

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

I understand that the key/value pairs are a NameValueCollection. The problem I face is that I wish to change the value either a deployment time or at runtime (either is fine with me) so that someValue will be someOtherValue based on the environment installed in.

Currently I make some other config changes at runtime, but those are in the AppSettings section, and thus easy to get at. I have found many references in my search for a solution, but they seem to rely on the section having a custom class, not the NameValueCollection that I'm faced with.

Does anyone know the best way to modify this data? A runtime change with a ConfigurationManag开发者_JAVA技巧er.RefreshSection() would be more in line with my current code, but I'm open to suggestions during the install phase as well.

Edit: This works at runtime. This is how I was handling the old configuration overrides.

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

My attempt to do the same for another section:

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;

So far, so good. However, I don't see a method that allows me to replace the old XML with my modified data. Is it possible at runtime?

As an aside: I tried modifying the app.config.deploy file by hand. That just gives me a validation error as the modification is detected by the installer and it refuses to proceed. I really like the auto deploy, and the prior override worked great.


One thing you could do is add a first-time-running section to your code that does additional setup, such as modifying the application config file. To detect whether this setup needs to be done, your third-party config section could come pre-populated with dummy values that your application would recognize as belonging to a new install. For example, your config file could look like this:

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

And your Main method could look something like this:

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


For the sake of putting forward an idea that people can vote up or down (not that I have seen much other than tumbleweed around this question), I'm thinking of using the technique posted here: http://www.devx.com/dotnet/Article/10045

The basic idea is to make ClickOnce deploy a shim application which will just do an XCOPY deployment of the main application (and as it isn't using the app.config file I can just use standard XML modification techniques and be done with it).

Alternatively, as this application is deployed from the network, I may just put the assembly on the network and work with the permission system to grant it access to the folders and database it requires. Any thoughts?


I would write a custom installer and, in the AfterInstall event, modify the config file using the XML mechanisms you have above. I don't know, though, how or if that works with ClickOnce.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号