34

Is it possible to relocate the whole App.Config file to a custom path?

It seems a bit odd that the config file resides in the same folder as the exe, with Windows' new approcah of saving all program settings in c:\ProgramData and all.

An additional requirement we have is to programatically specify where to find the app.config file. The reason for this being that we spawn different service instances from the same exes, and would like to store each service's app.config in that service's settings folder under c:\ProgramData\\.

Ries
  • 2,844
  • 4
  • 32
  • 45
  • the default behavious is the a program has 1 default config file in its own director and each user has their own config file stored in their user area, bu default any settings set to user will be pulled from the users config unless not present then it will use the programs config – MikeT Oct 03 '13 at 10:06

9 Answers9

43

If still relevant, we have used the following I found on another suggested answer to another question here on Stack Overflow...

AppDomain.CurrentDomain.SetData ("APP_CONFIG_FILE", "path to config file")

Worked great for us when we had issues loading app.config from DLL only...

newby
  • 497
  • 1
  • 6
  • 13
  • 4
    If you use that technique certain sections of configuration will not be applied. For example [``](https://msdn.microsoft.com/en-us/library/6bs4szyc(v=vs.110).aspx). – Leonid Vasilev Apr 10 '17 at 16:16
18

Each AppDomain has/can have its own configuration file. The default AppDomain created by CLR host uses programname.exe.config; if you want to provide your own configuration file, create separate AppDomain. Example:

// get the name of the assembly
string exeAssembly = Assembly.GetEntryAssembly().FullName;

// setup - there you put the path to the config file
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = System.Environment.CurrentDirectory;
setup.ConfigurationFile = "<path to your config file>";

// create the app domain
AppDomain appDomain = AppDomain.CreateDomain("My AppDomain", null, setup);

// create proxy used to call the startup method 
YourStartupClass proxy = (YourStartupClass)appDomain.CreateInstanceAndUnwrap(
       exeAssembly, typeof(YourStartupClass).FullName);

// call the startup method - something like alternative main()
proxy.StartupMethod();

// in the end, unload the domain
AppDomain.Unload(appDomain);

Hope that helps.

mYsZa
  • 505
  • 3
  • 12
  • I tried this for an application that used WCF, but it wouldn't work (correct me if I'm wrong). Any ideas on how to relocate app.config for an app that uses WCF? – Contango Nov 10 '10 at 00:46
  • @Gravitas: If it is still relevant for you: I found a solution: http://stackoverflow.com/questions/6150644/change-default-app-config-at-runtime/6151688#6151688 – Daniel Hilgarth May 27 '11 at 12:17
  • Useful to learn that programName.exe.config is where app.config ends up. Thank you for the information. – Rod Hartzell Oct 29 '14 at 15:36
8

I know this is an old question, but for those who just want to have their app.config in a different location then their binary output build location, the following works as microsoft intended it (and thus no need re-read and re-write the file to disk)

  • Define an app.config as you always do.
  • Define another config file where you want to have the actual configuration file
  • Change the app.config so that it refers to the configuration file

At runtime the settings from the configuration file will override the settings in the app.config (if present). And you are done.

Example app.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
    </startup>
  <appSettings file="..\Config\settings.config">
    <add key="port" value="1001"/>
  </appSettings>
</configuration>

Note the file="..\Config\settings.config". You are completely free to define the path to the location where you want your users to change settings.

Example of the actual configuration file

<?xml version="1.0" encoding="utf-8"?>
<appSettings>
  <add key="port" value="1234"/>
</appSettings>

At runtime the setting port will have the value 1234.

More info see msdn

bas
  • 13,550
  • 20
  • 69
  • 146
  • 7
    Note: This just for loading the `appSettings` section from a separate file. It isn't loading the entire app.config from another location – David Gardiner Jan 19 '16 at 23:34
7

This worked for me.. (taken from http://msdn.microsoft.com/en-us/library/system.configuration.appsettingssection.aspx)

// open config
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

// update appconfig file path
config.AppSettings.File = "C:\\dev\\App.config";

// Save the configuration file.
config.Save(ConfigurationSaveMode.Modified);

// Force a reload in memory of the changed section.
ConfigurationManager.RefreshSection("appSettings");

Then when you call

NameValueCollection settings = System.Configuration.ConfigurationManager.AppSettings;

or any operation to fetch the app config, the new path is used.

Hope this might help someone else who has same problem!

namford
  • 1,171
  • 1
  • 14
  • 13
  • This approach works if you have an app.config with only class at root level. Otherwise it throws an exception. (VB.NET 4.5.2) – Eric Draven Apr 24 '18 at 10:10
2

I am sorry if I misunderstand your request but can you not use

ConfigurationManager.OpenExeConfiguration Method (String)

Based on the change, is it possible that you can use

AppDomainSetup.ConfigurationFile Property

Adriaan Stander
  • 162,879
  • 31
  • 289
  • 284
  • 2
    This would help for cases where I manually read setting from the config, but not for the sections that .NET reads itself, such as WCF setup and ConnectionStrings etc. – Ries Dec 03 '09 at 09:07
  • 1
    You can only modify AppDomainSetup.ConfigurationFile during the process of creating a new app domain. You can't modify it once your app domain is running. – Tim Robinson Dec 03 '09 at 09:22
  • @Ries - I agree - I just tried it to load a custom .config file for WCF, and it just didn't work (correct me if I'm wrong!). Any ideas on how to relocate the .config file for an app that uses WCF? – Contango Nov 10 '10 at 00:47
2

This is an ancient question, but I ran into this same problem and came up with a hacky workaround from a few minutes in reflector:

static public class ConfigHack {
    static public void OverrideAppConfig(string path) {
        ((AppDomainSetup)
            typeof(AppDomain)
                .GetField("_FusionStore", BindingFlags.NonPublic | BindingFlags.Instance)
                .GetValue(AppDomain.CurrentDomain))
        .ConfigurationFile = path;
    }

    static public void ResetConfigManager() {
        typeof(ConfigurationManager)
            .GetField("s_initState", BindingFlags.Static | BindingFlags.NonPublic)
            .SetValue(null, 0);
    }
}

I've only used it on .NET2, but it looks the same in 4 in reflector. Of course I wouldn't recommend shipping this :P I only use it for quick internal things.

wrmsr
  • 86
  • 1
  • 3
  • 1
    If using .NET 4.5, you can replace this code with "AppDomain.CurrentDomain.SetData ("APP_CONFIG_FILE", "path to config file")" (see answer below). I have verified this and it works perfectly (it loads a new app.config into the current app domain). – Contango Jan 15 '14 at 12:43
  • Yes, APP_CONFIG_FILE works for me. Still have to use the ResetConfigManager() hack and RefreshSection("appSettings"). This whole .net configuration thing calls for a complete rewrite! – Robert Cutajar May 11 '16 at 11:44
1

You could use astander's approach of calling OpenExeConfiguration. If you literally want to relocate your config file, you'll have to create your own app domain. In the process of setting up your app domain you get the chance to specify where the config file is located.

BTW, .NET config files aren't great for configuration, at least not the sort that users can modify: they're not like INI files or the registry. If you want flexibility over where your configuration comes from you're better off storing it separately.

Tim Robinson
  • 53,480
  • 10
  • 121
  • 138
0

If u use the registry, your problem can be resolved.

Mhmetengineer
  • 49
  • 1
  • 7
-3

MSDN probably would help...

The element simplifies servicing for component assemblies. If one or more applications use an assembly that has a configuration file residing in a well-known location, the configuration files of the applications that use the assembly can use the element to include the assembly configuration file, rather than including configuration information directly. When the component assembly is serviced, updating the common configuration file provides updated configuration information to all applications that use the assembly

KMån
  • 9,896
  • 2
  • 31
  • 41