I'm trying to work with a settings.settings file in my project. There are values that need to be shared between the .exe file and various DLLs. I'd rather not just pass these values around, I'd like to access them when I need them but each project sets up its values with slightly different names and therefore aren't reachable by the other projects.
Is there any way to share the contents of the app.config file between an .exe and a .dll using the settings.settings approach? Or do I need to go back to using ConfigurationManager in order to do this?
Just put your settings in the App.config file, and read them from your dll. In fact I believe it's the only place your dll will look for settings/config, local config for the dll is ignored.
Here's a quick example to ensure the dll has no strong references to the application. This code isn't great but you get the idea.
private string GetSettingValue(string key)
{
string executingAssembly = Assembly.GetEntryAssembly().GetName().Name;
string sectionName = "applicationSettings/" + executingAssembly
+ ".Properties.Settings";
ClientSettingsSection section =
(ClientSettingsSection)ConfigurationManager.GetSection(sectionName);
// add null checking etc
SettingElement setting = section.Settings.Get(key);
return setting.Value.ValueXml.InnerText;
}
Alternatively have a common dll with the shared settings and take a dependency from each assembly that needs to share the config. This is far cleaner.
Related
I have searched for a while quite fruitlessly for a way to do this.
I am working on a project the has many parts, most of which i can not directly access, but it is extensible. So I have written a dll for it, but the problem is that I need to be able to supply some sort of settings/config that can be updated with out having to recompile the dll.
I don't have access to a main exe's app.config. and the settings/dll.config that vs2010 creates is not being picked up by the dll.
Is this actually possible? a standalone operational config file for a dll?
new update. - I have created a settings.settings file and the all successfully picks up the config data but it seems to bake it into the file when its compiled, when i edit the config after deployment it does not pick up the changes. I tried the first answer below and it didn't work.
thanks
Yes, using the System Configuration namespace you can create a ConfigurationSection which can be used to store any configuration properties you like:
public class MyConfigurationSection : ConfigurationSection
{
[ConfigurationProperty("MyProperty")]
public string MyProperty
{
get { return (string)this["MyProperty"] }
set { this["MyProperty"] = value;
}
}
Then in your assembly project you can read your assembly specific configuration. If your assembly is called MyAssembly, then GetSection() will look for a configuration file called MyAssembly.dll.config:
var myConfig = (MyConfigurationSection)ConfigurationManager.GetSection("sectionName");
Console.WriteLine(myConfig.MyProperty);
I didn't try this specific example, but I have had to do this before. Hope this helps!
I'm trying to use application settings with a C#.NET project I am working on. But I can't seem to get it to return anything other then the default values. Through the project properties I've added a single setting, DBConnectionString, and set its value to a connection string I want to use. Its scope is set to "application".
Doing this created a number of files including Settings.settings, Settings.Designer.CS, and app.conifg. From what I understand the two Settings.* files define a custom Settings class that derives from ApplicationSettingsBase. The Settings class then has custom, type safe, properties that can be used to set and retrieve each setting. The app.config file is a XML file that stores the actual settings values.
When I build my project it looks like the app.config file is copied to the target directory as MyApplication.dll.config. My program runs fine and is able to use the default connection string.
Next I tried to edit the MyApplicaiton.dll.config file to change the connection string. I ran my program again, but it continued to use the default value. I noticed that in my Settings.Designer file there is a DefaultSettingValueAttribute with the original default string. I tried removing this attribute, but then when I tried to retrieve the connection string setting it just returned null.
This is the code I'm using to read the connection string.
string conn = Properties.Settings.Default.DbConnectionString
What am I doing wrong? How can I get it to return the value in the settings file and not the default value?
Update:
Sorry I should have mentioned this. I'm actually writing a plug-in for another application through a public API. So my project is a DLL not an EXE.
You cannot read settings from *.dll.config files. If you library needs any special settings you need to put them in your app.config or web.config files.
EDIT: You can include the external config files in the main application or web config file. Look here for details.
This question discusses how to manage configuration files for large projects.
Settings files and .config files are different things (I do not know why VS automatically added a .config when you created a Settings file). But, the settings file is compiled into a class and is referenced like you said. If you decompile the dll with .NET reflector the Settings class will be in there. It is used for holding constant values or external resources. For example: error message strings, icons, or images.
The config file is for settings which can change frequently or between environments (dev, test, prod). For a connection string you should use the <connectionStrings> section of the config file. And the property can be referenced using System.Configuration.ConfigurationManager[ "connectionStringName" ].
However, from your original post it looks like your .dll is going to be used in a larger project (either an .exe of web project). One thing to note is that all projects only use one .config file. And that is the config file for the main project. Websites the web.config file, and exe's use XXX.XXX.XXX.exe.config (as you saw, *.exe.config files are renamed copies of the app.config files). dll's do not have usable config files. All dll's will look at the main project's .config file to retrieve information.
If your connection string is never going to change then by all means use the Settings file. Otherwise, use a config file and let the developer of the main project determine what to populate the connection string with.
We have a Visual Studio 2010 solution that contains several C# projects in accordance with Jeffery Palermo's Onion Architecture pattern (http://jeffreypalermo.com/blog/the-onion-architecture-part-1/). We have a UI project that is an ASP.Net MVC project, and we have a C# Class Library project called Infrastructure that is referenced by the UI project. In our Infrastructure project we have added an app.config file to contain settings that are specific to the Infrastructure project. At runtime, the app.config file doesn't appear to be available to the Infrastructure project, only the web.config file contained in the UI project. We don't want to put settings that pertain to the Infrastructure project into the web.config file in the UI project, the UI has no need for those settings. How can we make the Infrastructure's app.config file available at runtime? We were thinking maybe we should put a Post Build Copy to copy the app.config out to the UI directory when the application is built - is that the right way to do this, or is there a better way?
Generally, you'll be told that this can't be done. However, you can certainly load a config file using the System.Configuration.ConfigurationManager.OpenExeConfiguration method. You can pass in the file path to your assembly (it doesn't have to be an executable, despite the method name).
Granted, this doesn't merge your assembly's config settings into the executing application's config settings, and I don't think that it should. Your assembly just has to know that it needs to retrieve its settings through a different mechanism than the System.Configuration.ConfigurationManager.GetSection function or the static AppSettings property on that class.
Below is a very simple example for a "Settings" class that loads a .config file for the assembly of which it is a part.
public static class Settings
{
public static System.Configuration.Configuration Configuration { get; private set; }
static Settings()
{
// load a .config file for this assembly
var assembly = typeof(Settings).Assembly;
Configuration = System.Configuration.ConfigurationManager.OpenExeConfiguration(assembly.Location);
if (Configuration == null)
throw new System.Configuration.ConfigurationErrorsException(string.Format("Unable to load application configuration file for the assembly {0} at location {1}.", assembly.FullName, assembly.Location));
}
// This function is only provided to simplify access to appSettings in the config file, similar to the static System.Configuration.ConfigurationManager.AppSettings property
public static string GetAppSettingValue(string key)
{
// attempt to retrieve an appSetting value from this assembly's config file
var setting = Configuration.AppSettings.Settings[key];
if (setting != null)
return setting.Value;
else
return null;
}
}
And the usage...
public class UsageExample
{
void Usage()
{
string mySetting = Settings.GetAppSettingValue("MySetting");
var section = Settings.Configuration.GetSection("MySection");
}
}
Now, you'll still have to work out build issues. Adding an "Application Configuration File" (App.config) item to your class library assembly does cause Visual Studio to copy it to that assembly's output folder as .dll.config, but it is not automatically copied to the output folder of any executable applications that reference that project. Therefore, you'd need to add a post-build step to copy the file to the appropriate location, as you mentioned.
I'd consider having a post-build step on the class library that copies the .config file out to a solution-level "Configurations" folder, then have a post-build step for executable projects to copy everything from the "Configurations" folder to the output folder. I'm not sure if that would actually work well, but if it does then you wouldn't be creating additional dependencies between projects in your post-build steps (that might make maintenance difficult).
EDIT: Ultimately, you should consider whether this is really what you want to be doing. It isn't the normal approach, and generally you might be better served by utilizing the other answer to this question that mentions using the configSource attribute.
Drawbacks to this approach that may not be obvious are that you won't be able to put settings for third-party components into your class library's config file and expect them to be used. For instance, if your class library is using log4net, you can't put log4net's settings in your class library's config file, because the log4net components still expect to load settings from the executable's config file.
Even if you post-build-copy the app.config it will not solve your problem. The application is still a web app, so the config system will use the web.config file. The settings will need to go in there one way or another. One way to still keep those settings a bit separate is to put them into a custom config section, and then put the settings for this section into a separate file. It will still need to be referenced from the web.config though (using a configSource attribute).
Thank you Dr. Wily's Apprentice ! I've added the function for getting the connection string as well:
public static string GetConnectionStringValue(string key)
{
var setting = Configuration.ConnectionStrings.ConnectionStrings[key];
if (setting != null)
return setting.ConnectionString;
else
return null;
}
I have a config file in my C# class library called MyLibrary.config, in vs 2008.
I created another project, say a simple console app, add reference by "Browsing" the MyLibrary.dll in the bin directory of the class library project, and when I compile, the MyLibrary.config is not including in the bin directory of the output in the console app.
How can I set it so I can include it when I reference the dll?
Cheers
You can't. Your console application is expecting to find a config file with prefix the same as the name as the console application (MyConsoleApplication.exe -> MyConsoleApplication.exe.config.).
In some situations you can share a config file by using the file attribute on the appSettings element:
<appSettings
file="path">
</appSettings>
Note that path is relative to the executing assembly.
As a side note, DLLs do not even use the config file that you've defined in the project. Again, configuration information is read from the a config file with prefix the same as the executing assembly. Thus, even when MyLibrary.dll tries to yank configuration information out of a config file, it will be reading the config file for the executing assembly, not MyLibrary.dll.config.
For more on how config files work, see MSDN.
The standard way to use a config file is to have it the same as the executable, adding a reference to a dll will not include its config file and as far as I know dll's don't load config files on their own, rather they rely on the executable that reference them.
Beyond not being able to do this, I would also advise against this approach.
Rather than trying to tighly couple your settings to the DLL library, consider more of a "Dependency Injection" type approach - i.e. where you pass in the value dependencies (i.e. settings) to the code you are calling (i.e. the library).
The advantage in this is you are not tied to a single method of storing settings. You can then use a database, different config file formats... even hard-coding. It also makes unit testing easier by removing the external file dependency.
There are different ways to implement this, however one example is to pass the configuration settings into the constructor of the class(s) that uses them.
I have a .NET 3.5 class library I built that reads an App.config file for values it needs. It can pull the config values just fine when I test it in Visual Studio. To test it, I just change the project to a console application and execute a method call.
I have the need to call this class library from many other .NET programs, and I want the class library to be self sufficient (I should be able to call it from any other program, and it should use its own config file, not know about any calling config file etc.).
I can add a reference to the dll (since I am still development I am using VS 2008, haven't thrown anything into the GAC yet) but the App.config that the class library is reading is from the calling program's App.config, not the class library's App.config.
The class library dll has it's config file in the same directory, so it should be able to find it just fine, and the calling application is named differently. I am using the standard key value pairs in the App.config (e.g. name of config file myClassLibrary.dll.config) and getting values out with the following line of code:
String myVal = ConfigurationSettings.AppSettings["myConfigSetting"];
Does anyone know how to fix this?
An app domain in C# can have only one assembly level app.config file. See here on MSDN. An executable will always start up an AppDomain and by default look for a config file with name: EXECUTABLE_NAME.config. For example, SampleApp01.exe will look for SampleApp01.exe.config as its configuration file.
you can place your configs in the machine.config file inside the framework folder by this way you can globally use your configuration in all .Net applications running in that machine,
I believe app.config will always be used by the executable. Just drop it in that directory.
They would do that to ensure the dll can be shared and not have to share the same .config file.
You might be able to create a link from the executable .config file
<appSettings configSource="\lib\app.config">
Or change its name, i don't understand how you can have both app.config files in the same directory..don't they have the same name?
<appSettings configSource="\lib.app.config">
I can't find a way to avoid getting the app.config for the calling dll/exe etc. The only way I have found is to use a hardcoded path and load it that way. Here is code I am using to do that:
using System.Configuration;
...
public static KeyValueConfigurationCollection getAppSettingsFromAppConfig(String appConfigPath) {
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = appConfigPath;
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
AppSettingsSection section = config.AppSettings;
KeyValueConfigurationCollection appsettings = section.Settings;
return appsettings;
}
You then have a collection of KeyValueConfigurationElement, which you can use .Value to get the string from config file with.