Search code examples
c#.netpathapp-config

How to change location of app.config


I want to change the location where my application looks for the app.config file.

I know that I can use ConfigurationManager.OpenExeConfiguration() to access an arbitrary config file - however, when the .Net Framework reads the config file (for ConnectionStrings or EventSources, for instance), it will look at the default location. I want to actually change the location, globally for the entire .Net Framework (for my application, of course).

I also know that I can use AppDomainSetup to change the location of the app.config for a new AppDomain. However, that doesn't apply to the primary AppDomain of the application.

I also know that I can override function Main() and create a new AppDomain as above and run my application in that new AppDomain. However, that has other side-effects - for instance, Assembly.GetEntryAssembly() will return a null reference.

Given how everything else works in .Net, I would expect there to be some way to configure the startup environment of my application - via a Application Manifest, or some such - but I have been unable to find even a glimmer of hope in that direction.

Any pointer would be helpful.

David Mullin


Solution

  • 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.