How to change location of app.config

天涯浪子 提交于 2019-11-28 23:57:43

I used the approach with starting another AppDomain from Main(), specifying the "new" location of the configuration file.

No issues with GetEntryAssembly(); it only returns null, when being called from unmanaged code - or at least it doesn't for me, as I use ExecuteAssembly() to create/run the second AppDomain, much like this:

int Main(string[] args)
{
   string currentExecutable = Assembly.GetExecutingAssembly().Location;

   bool inChild = false;
   List<string> xargs = new List<string>();
   foreach (string arg in xargs)
   {
      if (arg.Equals("-child"))
      {
         inChild = true;
      }
      /* Parse other command line arguments */
      else
      {
         xargs.Add(arg);
      }
   }

   if (!inChild)
   {
      AppDomainSetup info = new AppDomainSetup();
      info.ConfigurationFile = /* Path to desired App.Config File */;
      Evidence evidence = AppDomain.CurrentDomain.Evidence;
      AppDomain domain = AppDomain.CreateDomain(friendlyName, evidence, info);

      xargs.Add("-child"); // Prevent recursion

      return domain.ExecuteAssembly(currentExecutable, evidence, xargs.ToArray());
   }

   // Execute actual Main-Code, we are in the child domain with the custom app.config

   return 0;
}

Note that we are effectively rerunning the EXE, just as a AppDomain and with a different config. Also note that you need to have some "magic" option that prevents this from going on endlessly.

I crafted this out from a bigger (real) chunk of code, so it might not work as is, but should illustrate the concept.

I am not sure why you want to change the location of your config file - perhaps there can be different approach for solving your actual problem. I had a requirement where I wanted to share configuration file across related applications - I had chosen to use own xml file as it had given me extra benefit of having complete control over the schema.

In your case, it's possible to externalize sections of your config file to a separate file using configSource property. See here under "Using External Configuration Files" to check how it has been done for connection strings section. Perhaps, this may help you.

var configPath = YOUR_PATH;
if (!Directory.Exists(ProductFolder))
{
    Directory.CreateDirectory(ProductFolder);
}

if (!File.Exists(configPath))
{
    File.WriteAllText(configPath, Resources.App);
}

var map = new ExeConfigurationFileMap
{
    ExeConfigFilename = configPath,
    LocalUserConfigFilename = configPath,
    RoamingUserConfigFilename = configPath
};

Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);

Then use config member as you want.

Another approach is to leave the config file with the executable file and move the relevant changeable sections to external xml files which can be in whatever location you choose.

If you are using your config file in a readonly capacity, then you can add the relevant chunks to an XML file in a different location using XML Inlcude. This won't work if you are trying to write values back directly to app.config using the Configuration.Save method.

app.config:

<?xml version="1.0"?>
<configuration xmlns:xi="http://www.w3.org/2001/XInclude">
    <appSettings>
      <xi:include href="AppSettings.xml"/>
    </appSettings>
  <connectionStrings>
    <xi:include href="ConnectionStrings.xml"/>
  </connectionStrings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/></startup>
</configuration>

ConnectionStrings.xml:

<?xml version="1.0"?>
<add name="Example1ConnectionString"
        connectionString="Data Source=(local)\SQLExpress;Initial Catalog=Example1DB;Persist Security Info=True;User ID=sa;Password=password"
        providerName="System.Data.SqlClient" />
<add name="Example2ConnectionString"
        connectionString="Data Source=(local)\SQLExpress;Initial Catalog=Example2DB;Persist Security Info=True;User ID=sa;Password=password"
        providerName="System.Data.SqlClient" />

AppSettings.xml:

<?xml version="1.0"?>
<add key="Setting1" value="Value1"/>
<add key="Setting2" value="Value2"/>

A file URI looks like this:

file:///C:/whatever.txt

You can even define failover files in case the one you are trying to reference is missing. This pattern is from https://www.xml.com/pub/a/2002/07/31/xinclude.html:

<xi:include href="http://www.whitehouse.gov/malapropisms.xml">
  <xi:fallback>
    <para>
      This administration is doing everything we can to end the stalemate in
      an efficient way. We're making the right decisions to bring the solution
      to an end.
    </para>
  </xi:fallback>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!