How do I retrieve AppSettings from the assembly config file? - c#

I would like to retrieve the AppSetting key from the assembly config file called: MyAssembly.dll.config. Here's a sample of the config file:
<configuration>
<appSettings>
<add key="MyKey" value="MyVal"/>
</appSettings>
</configuration>
Here's the code to retrieve it:
var myKey = ConfigurationManager.AppSettings["MyKey"];

Using the OpenMappedExeConfiguration gives you back a "Configuration" object which you can use to peek into the class library's config (and the settings that exist there will override the ones by the same name in the main app's config):
ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = "ConfigLibrary.config";
Configuration libConfig = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
AppSettingsSection section = (libConfig.GetSection("appSettings") as AppSettingsSection);
value = section.Settings["Test"].Value;
But those settings that are unique to the main app's config and do not exist in the class library's own config are still accessible via the ConfigurationManager static class:
string serial = ConfigurationManager.AppSettings["Serial"];
That still works - the class library's config only hides those settings that are inside its config file; plus you need to use the "libConfig instance to get access to the class library's own config settings, too .
The two worlds (main app.config, classlibrary.config) can totally and very happily co-exist - not a problem there at all!
Marc

var appSettings = ConfigurationManager.OpenExeConfiguration((Assembly.GetAssembly(typeof(MYASSEMBLY))).Location).AppSettings;
then you can do as above.

You can also open it up as an XmlDocument and navigate the document with Xpath. THen there is always LinqToXml

var uri = new Uri(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase));
var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = Path.Combine(uri.LocalPath, "MyAssembly.dll.config") };
var assemblyConfig = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

Using System.Configuration
Public Shared Function AppDomainConfiguration() As Configuration
Dim fileMap As New ExeConfigurationFileMap
fileMap.ExeConfigFilename = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
Return ConfigurationManager.OpenMappedExeConfiguration(fileMap,Configuration.ConfigurationUserLevel.None)
End Function

Related

How to read any '.config' file in c# but its own

How to read a .config file using ConfigurationManager or any other way.
Below is my code which gives the following error:
'System.Configuration.ConfigurationElement.this
[System.Configuration.ConfigurationProperty] is inaccessible due to
its protection level.'
ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap();
//txtConfigFile gets a config file path at runtime
configFileMap.ExeConfigFilename = txtConfigFile.FilePath;
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
//Configpath's value is assigned to a textbox named txtConfigPath
txtConfigPath = config.AppSettings["Configpath"];
Configuration.AppSettings returns an AppSettingSections object, AppSettingSections is derived from ConfigurationSection which is derived from ConfigurationElement which defines a this[] operator as protected internal, which mean that it is "inaccessible due to its protection level."
You should try AppSettings.Settings:
txtConfigPath = config.AppSettings.Settings["Configpath"];

Using Configuration manager?

Looking at an example where the server receives a file on the streamReader from the client.
string key = "UploadSalesFileToServer";
GetValue(key);
is added to the function, which uses:
private static string GetValue(string name)
{
var fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = System.Web.HttpContext.Current.Server.MapPath("~/Modules/Work/web.config");
var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
string configValue = configuration.AppSettings.Settings[name].Value;
return configValue;
}
and in web.config I use:
<appSettings>
<add key="UploadSalesFileToServer"
value="1111-fasad-32233-ffdsff"/>
</appSettings>
Can anyone tell me what happens here through out? the app settings is used to check the correct file is being received?
GetValue trying to read config value from configuration file which is not exactly application configuration and situated in different directory under relative path "~/Modules/Work/web.config"

AppSettings from custom files

I am struggling with the configuration and setting classes in .NET 2.0
If the following is contaned in a file called app.config
<config>
<appSettings>
<add key="Foo" value="Hello World!"/>
</appSettings>
</config>
I know I can access the appSetting by
// this returns "Hello World!"
ConfigurationManager.AppSettings["Foo"]
However if the file is called app1.config (or any other name) I cannot access the appSetting.
As long as I understand, with ConfigurationManager.OpenExeConfiguration I should read custom config setting files.
Configuration conf = ConfigurationManager.OpenExeConfiguration(#"..\..\app1.config");
// this prints an empty string.
Console.WriteLine(conf.AppSettings.Settings["Foo"]);
However conf.AppSettings.Settings["Foo"] returns an empty string.
I have also tried the following code but no success
ExeConfigurationFileMap exeFileMap = new ExeConfigurationFileMap();
exeFileMap.ExeConfigFilename = System.IO.Directory.GetCurrentDirectory()
+ "\\App1.config";
Configuration myConf = ConfigurationManager.OpenMappedExeConfiguration
(exeFileMap, ConfigurationUserLevel.None);
// returns empty string as well
Console.WriteLine(myConf.AppSettings.Settings["Foo"]);
How to read setting from a file not called app.config?
I have created custom file myCustomConfiguration and changes its property Copy to Output Directory to true
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="Foo" value="Hello World!"/>
</appSettings>
</configuration>
In CS file
static void Main(string[] args)
{
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "myCustomConfiguration.config");
Dictionary<string, string> dictionary = GetNameValueCollectionSection("appSettings", filePath);
//To get your key do dictionary["Foo"]
Console.WriteLine(dictionary["Foo"]);
Console.ReadLine();
}
private static Dictionary<string, string> GetNameValueCollectionSection(string section, string filePath)
{
var xDoc = new XmlDocument();
var nameValueColl = new Dictionary<string, string>();
var configFileMap = new ExeConfigurationFileMap { ExeConfigFilename = filePath };
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
string xml = config.GetSection(section).SectionInformation.GetRawXml();
xDoc.LoadXml(xml);
XmlNode xList = xDoc.ChildNodes[0];
foreach (XmlNode xNodo in xList.Cast<XmlNode>().Where(xNodo => xNodo.Attributes != null))
{
nameValueColl.Add(xNodo.Attributes[0].Value, xNodo.Attributes[1].Value);
}
return nameValueColl;
}
Although this is working but I am also looking for better approach.
You should make use of a Settings-File, it's way more comfortable to use, has save and load methods and you can name it what ever you want. Eg. my Settings-File is called "EditorSettings.settings" and I access its properties like this:
MyNamespace.MyProject.EditorSettings.Default.MyProperty1

Reading custom configuration section's key values in C#

I need to read key values from custom sections in app/web.config.
I went through
Reading a key from the Web.Config using ConfigurationManager
and
How can I retrieve list of custom configuration sections in the .config file using C#?
However, they do not specify how to read a custom section when we need to explicitly specify the path to the configuration file (in my case, the configuration file is not in it's default location)
Example of my web.config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<MyCustomTag>
<add key="key1" value="value1" />
<add key="key2" value="value2" />
</MyCustomTag>
<system.web>
<compilation related data />
</system.web>
</configuration>
in which i need to read key value pairs inside MyCustomTag.
When i try (configFilePath is the path to my configuration file):-
var configFileMap = new ExeConfigurationFileMap { ExeConfigFilename = configFilePath };
var config =
ConfigurationManager.OpenMappedExeConfiguration(
configFileMap, ConfigurationUserLevel.None);
ConfigurationSection section = config.GetSection(sectionName);
return section[keyName].Value;
I get a error stating "Cannot access protected internal indexer 'this' here" at section[keyName]
Unfortunately, this is not as easy as it sounds. The way to solve the problem is to get file config file with ConfigurationManager and then work with the raw xml. So, I normally use the following method:
private NameValueCollection GetNameValueCollectionSection(string section, string filePath)
{
string file = filePath;
System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument();
NameValueCollection nameValueColl = new NameValueCollection();
System.Configuration.ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = file;
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
string xml = config.GetSection(section).SectionInformation.GetRawXml();
xDoc.LoadXml(xml);
System.Xml.XmlNode xList = xDoc.ChildNodes[0];
foreach (System.Xml.XmlNode xNodo in xList)
{
nameValueColl.Add(xNodo.Attributes[0].Value, xNodo.Attributes[1].Value);
}
return nameValueColl;
}
And the call of the method:
var bla = GetNameValueCollectionSection("MyCustomTag", #".\XMLFile1.xml");
for (int i = 0; i < bla.Count; i++)
{
Console.WriteLine(bla[i] + " = " + bla.Keys[i]);
}
The result:
Formo makes it really easy, like:
dynamic config = new Configuration("customSection");
var appBuildDate = config.ApplicationBuildDate<DateTime>();
See Formo on Configuration Sections

App config for dynamically loaded assemblies

I'm trying to load modules into my application dynamically, but I want to specify separate app.config files for each one.
Say I have following app.config setting for main app:
<appSettings>
<add key="House" value="Stark"/>
<add key="Motto" value="Winter is coming."/>
</appSettings>
And another for library that I load using Assembly.LoadFrom:
<appSettings>
<add key="House" value="Lannister"/>
<add key="Motto" value="Hear me roar!"/>
</appSettings>
Both libraries have a class implementing the same interface, with the following method:
public string Name
{
get { return ConfigurationManager.AppSettings["House"]; }
}
And sure enough calls to Name from both main class and loaded assembly class output Stark.
Is there a way to make main app use its own app.config and each loaded assembly use theirs? Names of config files are different in the output, so that should be possible I think.
Ok, here's the simple solution I ended up with:
Create the follow function in the utility library:
public static Configuration LoadConfig()
{
Assembly currentAssembly = Assembly.GetCallingAssembly();
return ConfigurationManager.OpenExeConfiguration(currentAssembly.Location);
}
Using it in dynamically loaded libraries like this:
private static readonly Configuration Config = ConfigHelpers.LoadConfig();
No matter how that library gets loaded it uses the correct config file.
Edit:
This might be the better solution for loading files into ASP.NET applications:
public static Configuration LoadConfig()
{
Assembly currentAssembly = Assembly.GetCallingAssembly();
string configPath = new Uri(currentAssembly.CodeBase).LocalPath;
return ConfigurationManager.OpenExeConfiguration(configPath);
}
To copy file after build you might want to add the following line to post-build events for asp app (pulling the config from library):
copy "$(SolutionDir)<YourLibProjectName>\$(OutDir)$(Configuration)\<YourLibProjectName>.dll.config" "$(ProjectDir)$(OutDir)"
As far as I know, you need separate application domains for the app.config to work separately. The creation of an AppDomainSetup allows you to specify which config file to use. Here's how I do it:
try
{
//Create the new application domain
AppDomainSetup ads = new AppDomainSetup();
ads.ApplicationBase = Path.GetDirectoryName(config.ExePath) + #"\";
ads.ConfigurationFile =
Path.GetDirectoryName(config.ExePath) + #"\" + config.ExeName + ".config";
ads.ShadowCopyFiles = "false";
ads.ApplicationName = config.ExeName;
AppDomain newDomain = AppDomain.CreateDomain(config.ExeName + " Domain",
AppDomain.CurrentDomain.Evidence, ads);
//Execute the application in the new appdomain
retValue = newDomain.ExecuteAssembly(config.ExePath,
AppDomain.CurrentDomain.Evidence, null);
//Unload the application domain
AppDomain.Unload(newDomain);
}
catch (Exception e)
{
Trace.WriteLine("APPLICATION LOADER: Failed to start application at: " +
config.ExePath);
HandleTerminalError(e);
}
Another way you could go about getting the desired effect would be to implement your configuration values inside a resource file compiled into each of your DLLs. A simple interface over the configuration object would allow you to switch out looking in an app.config versus looking in a resource file.
It may work if you change the code little bit:
public string Name
{
get {
Configuration conf = ConfigurationManager.OpenExeConfiguration("library.dll");
return conf.AppSettings.Settings["House"].Value;
}
}

Categories