Modifying config sections in App.config either at runtime or install time
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.
精彩评论