I created a command-line application and moved a lot of its config into a standard Settings file. All settings are declared as Scope = Application, because there is nothing user-specific about the logic in the application. I access the values throughout the code with
Properties.Settings.Default.<whatever>
This works well as it runs automatically on a schedule. Updating values in the config file are reflected in the output.
Some time later, I created a basic GUI (in the same namespace) to launch the command-line application directly (through a separate constructor). I haven't done a huge amount of .Net programming, but I'm basically using my CLI application like a DLL (I don't know if there's a proper term for this; in my output folder, all I need is GUI.exe, CLI.exe and CLI.exe.config and it works). However, I've noticed that when launched this way, the CLI.exe.config file is not loaded; the CLI application uses only its compiled-in defaults. I was hoping the config file method would work in this instance.
I've tried the following methods to force loading the config file but so far have drawn a blank:
1:
ConfigurationManager.RefreshSection("appSettings")
2:
ExeConfigurationFileMap configFile = new ExeConfigurationFileMap();
configFile.ExeConfigFilename = Path.Combine(Environment.CurrentDirectory, System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".exe.config");
ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None).Save(ConfigurationSaveMod.Modified);
ConfigurationManager.RefreshSection("appSettings");
3:
Properties.Settings.Default.Reload();
None of these produce errors, but the Properties.Settings.Default.Value
I have modified in the config file is not updated. Is there a way to accomplish what I need here?
Edit: here is a sample of my CLI.exe.config file if it helps illustrate what I'm trying to accomplish here:
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="CLI.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
</sectionGroup>
</configSections>
<connectionStrings/>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
<applicationSettings>
<CLI.Properties.Settings>
<setting name="URLBase" serializeAs="String">
<value>https://cloud.mycompany.com/</value>
</setting>
<setting name="URLPage" serializeAs="String">
<value>/inventory.aspx#view/Invoice/</value> <!-- This is the value I'm trying to change -->
</setting>
...
I should also mention that I've also tried 'applicationSettings' in place of 'appSettings' in the code above.
Make Sure the access modifier has been set to public. Launching with 'GetExecutingAssembly' will not load the CLI config if it has been triggered by the GUI.EXE since this IS the executing assembly. take a look at this:
Actual config
file which will have your runtime settings will depend on your application's entry point.
If you start your CLI.exe
directly, it will use a user settings file inside a subfolder inside user's local app data folder, similar to:
AppData\Local\CLI\CLI.exe\1.2.3.4\user.config
However, if you use a different entry point (CLI.exe
), which references GUI.exe
, all calls to Properties.Settings
will use a completely different user.config
instance, located in (something like):
AppData\Local\GUI\GUI.exe\1.2.3.4\user.config
Application-wide settings file (.exe.config
) which is placed in your output folder, next to the executable, only provides default settings for these user settings, or read-only application settings. Allowing the application to write to this file would mean it would have write access to Program Files
subfolders, which is not possible without elevated permissions.
The simplest solution to get the same user settings when you change your entry point is to copy the user.config
file from the CLI
app data folder to the appropriate folder for the new entry point.
(update for app setting)
It works the same for application settings (i.e. .config
files in your output folder). If you originally had:
<!-- CLI.exe.config -->
<configuration>
<!-- setting section definitions -->
<configSections>
<sectionGroup name="userSettings" ... >
<section name="CLI.CliSettings" ... />
</sectionGroup>
<sectionGroup name="applicationSettings" ... >
<section name="CLI.CliSettings" ... />
</sectionGroup>
</configSections>
<!-- defaults for user settings (runtime changes are stored to appdata) -->
<userSettings>
<CLI.CliSettings>
<setting name="SomeUserCliSetting" serializeAs="String">
<value>Some CLI user setting</value>
</setting>
</CLI.CliSettings>
</userSettings>
<!-- application settings (readonly) -->
<applicationSettings>
<CLI.CliSettings>
<setting name="SomeAppCliSetting" serializeAs="String">
<value>Some CLI app setting</value>
</setting>
</CLI.CliSettings>
</applicationSettings>
</configuration>
And your GUI.exe.config was:
<!-- GUI.exe.config -->
<configuration>
<configSections>
<sectionGroup name="userSettings" ... >
<section name="GUI.GuiSettings" ... />
</sectionGroup>
<sectionGroup name="applicationSettings" ... >
<section name="GUI.GuiSettings" ... />
</sectionGroup>
</configSections>
<userSettings>
<GUI.GuiSettings>
<setting name="SomeGuiUserSetting" serializeAs="String">
<value>Some GUI user setting</value>
</setting>
</GUI.GuiSettings>
</userSettings>
<applicationSettings>
<GUI.GuiSettings>
<setting name="SomeGuiAppSetting" serializeAs="String">
<value>Some GUI app setting</value>
</setting>
</GUI.GuiSettings>
</applicationSettings>
</configuration>
Then your resulting .config file should contain all sections:
<!-- GUI.exe.config -- merged configuration sections -->
<configuration>
<configSections>
<sectionGroup name="userSettings" ... >
<section name="GUI.GuiSettings" ... />
<section name="CLI.CliSettings" ... />
</sectionGroup>
<sectionGroup name="applicationSettings" ... >
<section name="GUI.GuiSettings" ... />
<section name="CLI.CliSettings" ... />
</sectionGroup>
</configSections>
<userSettings>
<GUI.GuiSettings>
<setting name="SomeGuiUserSetting" serializeAs="String">
<value>Some GUI user setting</value>
</setting>
</GUI.GuiSettings>
<CLI.CliSettings>
<setting name="SomeUserCliSetting" serializeAs="String">
<value>Some CLI user setting</value>
</setting>
</CLI.CliSettings>
</userSettings>
<applicationSettings>
<GUI.GuiSettings>
<setting name="SomeGuiAppSetting" serializeAs="String">
<value>Some gui app setting</value>
</setting>
</GUI.GuiSettings>
<CLI.CliSettings>
<setting name="SomeAppCliSetting" serializeAs="String">
<value>Some CLI app setting</value>
</setting>
</CLI.CliSettings>
</applicationSettings>
</configuration>
(it's possible I mixed up some values while writing this, but you get the idea).
There is also a tool I found by googling: XmlConfigMerge on CodeProject - I haven't tried it but presumably it does the same thing automatically, so you might want to check it out and include it into your build scripts.
来源:https://stackoverflow.com/questions/33234912/app-config-how-to-force-load-from-file-at-runtime