37

I have added multiple app.config (each with a differet name) files to a project, and set them to copy to the output directory on each build.

I try and access the contents of each file using this:

System.Configuration.Configuration o = ConfigurationManager.OpenExeConfiguration(@"app1.config");

The code runs, but o.HasFile ends up False, and o.FilePath ends up "app1.config.config". If I change to code:

System.Configuration.Configuration o = ConfigurationManager.OpenExeConfiguration(@"app1");

Then the code bombs with "An error occurred loading a configuration file: The parameter 'exePath' is invalid. Parameter name: exePath".

If I copy/paste the config file (so I end up with app1.config and app1.config.config) then the code runs fine, however, I posit this is not a good solution. My question is thus: how can I use ConfigurationManager.OpenExeConfiguration to load a config file corretly?

user9659
  • 901
  • 2
  • 9
  • 19
  • .net provides a good article: https://learn.microsoft.com/en-us/dotnet/api/system.configuration.configurationmanager.openexeconfiguration?view=netframework-4.7.2 – Jeremy Ray Brown Feb 08 '19 at 16:05
  • An even better article: https://www.codeproject.com/Articles/19675/Cracking-the-Mysteries-of-NET-2-0-Configuration#t2 – Mike Lowery Aug 04 '20 at 18:38

4 Answers4

65

I can't remember where I found this solution but here is how I managed to load a specific exe configuration file:

ExeConfigurationFileMap map = new ExeConfigurationFileMap { ExeConfigFilename = "EXECONFIG_PATH" };
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
user1697877
  • 751
  • 1
  • 5
  • 3
  • 1
    That works! Crazy that it was that much work figuring out how to just read a lousy config file from a specified exact path, but thanks. – neminem Mar 12 '13 at 18:46
  • 1
    How do you use the resulting `config.AppSettings["somekey"]` (or `config.AppSettings.Settings[]`) without access permission errors? – Brent Faust Jul 12 '13 at 17:14
  • 1
    @Rubistro you have to check if the item exists (otherwise config.AppSettings["somekey"] returns null) and then use .Value – Jedidja Jan 24 '14 at 20:56
  • 1
    Brent, here's how to use the resulting config without access permissions errors: var settings = config.GetSection("SectionName") as AppSettingsSection; if (settings != null) Console.Write(settings.Settings["ConfigName"].Value); – Koshera Nov 15 '16 at 21:13
23

According to http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/3943ec30-8be5-4f12-9667-3b812f711fc9 the parameter is the location of an exe, and the method then looks for the config corresponding to that exe (I guess the parameter name of exePath makes sense now!).

user9659
  • 901
  • 2
  • 9
  • 19
  • 5
    Note that you can pass any path to an assembly, not just an exe. So you give "SomeLib.dll", it would open "SomeLib.dll.config". It's useful when your .NET project is really just a plugin for another app for which you don't want to deploy a .config next to its executable. – Ludovic Chabant Apr 09 '10 at 17:55
  • Yet, when I put a file called app.config in the directory of the dll, using "app" as the exePath parameter, I had to change the name of the file to app before it worked... – tobbenb3 Mar 05 '14 at 12:18
8

To avoid this problem altogether, you can read in the config file as an XML file, for example:

using System.Xml;
using System.Xml.XPath;    

XmlDocument doc = new XmlDocument();
doc.Load(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\..\\..\\..\\MyWebProject\\web.config");
string value = doc.DocumentElement.SelectSingleNode("/configuration/appSettings/add[@key='MyKeyName']").Attributes["value"].Value;
Francis Huang
  • 550
  • 5
  • 6
  • Thanks for the XPath way. I've been using ConfigurationManager for about two days now with Configuration.AppSettings.Settings.Count = 0. Your method at least sets the correct value for me. – TamusJRoyce Sep 19 '11 at 13:38
2
using System.Reflection;

try
{
    Uri UriAssemblyFolder = new Uri(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase));
    string appPath = UriAssemblyFolder.LocalPath;

    //Open the configuration file and retrieve 
    //the connectionStrings section.
    Configuration config = ConfigurationManager.
        OpenExeConfiguration(appPath + @"\" + exeConfigName);

    ConnectionStringsSection section =
        config.GetSection("connectionStrings")
        as ConnectionStringsSection;
}

At least, this is the method I use when encrypting and decrypting the connectionStrings section for my console/GUI apps. exeConfigName is the name of the executable including the .exe.

ronalchn
  • 12,225
  • 10
  • 51
  • 61