Why does XmlDocument read .config file, but ConfigurationManager does not? [duplicate] - c#

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?

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);

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!).

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;

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.

Related

How to access "user.config" of different application

The user.config file of an application can be accessed in C# by
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath
Now, I need to get the user.config of a DIFFERNT application, identified by the fullpath to its exe in order replace current applications user.config by that one.
Any suggestions how to do so?
Edit: Please notice that I am interested in the user.config (ConfigurationUserLevel.PerUserRoamingAndLocal), not the application level settings like app.config or Application.exe.config. The latter is accessable by the OpenExeConfiguration(string), but is not what I want.
What about the overload that accepts a string?
var config = ConfigurationManager.OpenExeConfiguration(pathToAssebmly);
Anyway it´s a bad idea to bind your assembly that way to another one. You should consider to copy the config-file into all your assemblies and change the parts that are specific to a given one.
EDIT: As you´re interested in the user-specific setting you may use the following which is taken from here:
string configFile = string.Concat(appName, ".config");
// Map the new configuration file.
ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap
{
ExeConfigFilename = configFile
};
var config = ConfigurationManager.OpenMappedExeConfiguration(
configFileMap,
ConfigurationUserLevel.PerUserRoamingAndLocal);

Cannot read settings using ConfigurationManager [duplicate]

I have a WinForms .exe with an App.config that has a bunch of User Scoped Settings that are set at runtime and saved.
I want to be able to use the WinForms app to change and save the settings and then click on button to do some work based on the those settings.
I also want to read the user settings in the same .config file from a sep. console app so I can schedule to work to be done as a scheduled task.
What is the best way to be able to do this?
Update:
I tried the reccommendation of using ConfigurationManager.OpenExeConfiguration as described in some of the answers like so.
Configuration config = ConfigurationManager.OpenExeConfiguration("F:\\Dir\\App.exe");
but when I try to retrieve a User Setting like so.
string result = config.AppSettings.Settings["DB"].ToString();
I get a Null reference error.
From code in the exe however the following correctly returns the DB name.
Properties.Settings.Default.DB
Where am I going wrong?
Update 2:
So based on some of the answers below I now can use the following to retrieve the raw XML of the section of the user.config file I am interested in from sep. ConsoleApp.
System.Configuration.ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = #"D:\PathHere\user.config";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap,ConfigurationUserLevel.None);
System.Configuration.DefaultSection configSection = (System.Configuration.DefaultSection)config.GetSection("userSettings");
string result = configSection.SectionInformation.GetRawXml();
Console.WriteLine(result);
But I am still unable to just pull the value for the specific element I am interested in.
this should do it :
var clientSettingsSection = (System.Configuration.ClientSettingsSection)(ConfigurationManager.GetSection("userSettings/YourApplicationName.Properties.Settings"));
var setting = clientSettingsSection.Settings.Get("yourParamName_DB_");
string yourParamName_DB = ((setting.Value.ValueXml).LastChild).InnerText.ToString();
You can use the ConfigurationManager class to open the configuration file of another executable.
Configuration conf = ConfigurationManager.OpenExeConfiguration(exeFilePath);
// edit configuration settings
conf.Save();
See ConfigurationManager.OpenExeConfiguration
If you are setting these values per user basis you may need to use the ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel) method instead of the current method you are using now.
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Environment.CurrentDirectory + "\\MyApp.exe.config";
//i have config in the same directory as my another app
System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
var settingsSection = (System.Configuration.ClientSettingsSection)config.GetSection("userSettings/MyApp.Properties.Settings");
var setting = settingsSection.Settings.Get("MySetting");
var param = ((setting.Value.ValueXml).LastChild).InnerText.ToString();
If you know the path to the config file try:
System.Configuration.Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration("configPath");
string myValue = config.AppSettings.Settings[ "myValue" ].Value;

Modifying a config section saves that section to a different config file

I have myapp.somenamespace.exe.config file with a connectionStrings section, which I need to encrypt. Also there are some other config settings that I want intact. So I wrote this small tool that would do just that:
class Program
{
static void Main(string[] args)
{
EncryptSection("myapp.somenamespace.exe.config", "connectionStrings");
}
static void EncryptSection(string fileName, string sectionName)
{
var config = ConfigurationManager.OpenExeConfiguration(fileName);
var section = config.GetSection(sectionName);
if (section.SectionInformation.IsProtected) return;
secction.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
config.Save();
}
}
What happens, it creates a new config file named myapp.somenamespace.exe.config.config - adding a duplicate .config extension, which only contains the encrypted section. It does not modify the original config file.
Any ideas why such an odd behavior and how I could fix that?
Change this line:
EncryptSection("myapp.somenamespace.exe.config", "connectionStrings");
to this:
EncryptSection("myapp.somenamespace.exe", "connectionStrings");
the documentation on MSDN states that the first parameter is in fact he path of the executable (exe) file and thus it's tacking on an additional .config during Save.

windows forms app.config on common files folder

I have an application that stores single username and password on the app.config file.
I currently have the app.config writable on runtime so that the user will be able to change it.
problem begins upon installation using a setup project , the app.config is installed on the program files which is not writable for any user.
So , i have changed the app.config location upon installation to the common files folder so it will be accessible for reading and writing for all users.
Now, upon installation it seems that the data stored there is inaccessible at all , using ConfigurationManager.AppSettings["networkPath"] for example returns empty strings.
what am i doing wrong ?
You can do it in two ways:
Give special permission to app config file in program files by your installer. We do it using innosetup. If you are incapable of it, then do it from your program startup:
static void Main()
{
GrantAccess()
}
private static bool GrantAccess()
{
FileInfo fInfo = new FileInfo(Assembly.GetEntryAssembly().Location + ".config");
FileSecurity dSecurity = fInfo .GetAccessControl();
fSecurity.AddAccessRule(new FileSystemAccessRule("everyone",
FileSystemRights.FullControl,
AccessControlType.Allow));
fInfo .SetAccessControl(fSecurity);
return true;
}
Else you can choose another location to place your appconfig file, and then read it like this:
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), Assembly.GetEntryAssembly().GetName().Name) + ".exe.config";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap,
ConfigurationUserLevel.None);
return config.AppSettings.Settings["Key"].Value);
This is a poor choice in my opinion.

Dynamically creating App.config with connection string if App.config does not exists in Application-Data folder

I need to do my code the following task. I wrote some code as below, but I am getting error while setting connection string. Looks like it does not have set property.
Check if App.config is exists in user’s “Application Data” folder.
If does NOT exists then create App.config with ConnectionString
If does exists then check if it was connection string or not, and if missing then add connection string.
string SomeConnectionString ="My Connection String goes here"
//Checking whether App.config file exits in "Application Data" folder or not
String appDataPath = Environment.GetFolderPath
(Environment.SpecialFolder.LocalApplicationData);
if (!File.Exists(appDataPath + "App.config"))
{
appDataPath = Path.Combine(appDataPath , "App.config");
Configuration config = ConfigurationManager.OpenExeConfiguration
(appDataPath );
var setting = config.ConnectionStrings.ConnectionStrings
["MyConnectionString"];
if (setting == null)
{
Configuration Config = ConfigurationManager.OpenExeConfiguration
(ConfigurationUserLevel.None);
config.ConnectionStrings.ConnectionStrings
["MyConnectionString"].ConnectionString = SomeConnectionString;
//I am getting error on line above. Looks like there is not set
//property on it
Config.Save(ConfigurationSaveMode.Modified,true);
ConfigurationManager.RefreshSection("connectionStrings");
}
}
else
{
//check whether it has Connection string or not
//if not then add connection string
}
The app.config is only that named in your program. During build process the file is renamed to [ApplicationName].exe.config. So name the file like this. But beware! Normally the program directory is not allowed for write access (only to administrators). Settings-API is the better way!!!!
Have you looked at the Settings API? This might be more appropriate for what you are doing.

Categories