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.
Related
I am developing a C# application in Mono and trying to use log4net. The logger works just fine when I load the configuration manually however, I would like something more elegant.
In the log4net documentation it states that a config can be loaded from the assembly by using the following (or similar) line:
[assembly: log4net.Config.XmlConfigurator(ConfigFileExtension="log4net",Watch=true)]
I have ensured the config file gets moved to the build directory and has that extension. I have also made sure the AssemblyInfo.cs is marked "Application Definition" in MonoDevelop. I do not know why this is not working. Does anybody have any ideas?
BTW: I have searched all over the place trying to find an answer. I also tried loading the config from a resource and that did not want to work either.
It is possible, but awkward, to use multiple config files with log4net. See the discussion here: log4net - configure using multiple configuration files
Are you doing logging within your .exe and your .dll?
Can you make do with a single config file?
Bear in mind this section from the documentation: "if you use configuration attributes you must invoke log4net to allow it to read the attributes. A simple call to LogManager.GetLogger will cause the attributes on the calling assembly to be read and processed. Therefore it is imperative to make a logging call as early as possible during the application start-up, and certainly before any external assemblies have been loaded and invoked."
Try and distill the issue down to a simple example.
Ensure your config file is name exename.exe.log4net
Ensure that you place the AssemblyAttribute you have in the quesion, into the AssemblyInfo.cs of your .exe
Ensure that you make a call to LogManager.GetLogger ASAP in your .exe, before invoking any code from your .DLL
I have the following projects:
MVC
Console application
Class library
Windows forms application
COM Library
All these applications need to use a single configuration file. As far as I understand, app.config files are for windows, console applications and class libraries when web.config are for the web projects.
The same configuration need to be accessible in all of these projects. I have read that it's suggested to use machine configuration file, but we won't always have access to that, therefore configuration files must reside within our solution.
I don't fully understand how the configuration files get build. Currently I wrote a simple project where I have the following:
Class library to store for serving configuration files. A have attempted to do this through reflection.
Windows application that should read the app.config from a class library.
When I execute the following code I expect to get a configuration file with test values:
_applicationSettings = ConfigurationManager.OpenExeConfiguration(
System.Reflection.Assembly.GetAssembly(typeof(WCSConfiguration)).Location
).AppSettings;
What I get instead is an empty application settings file.
Class library has the following App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="TestTextKey" value="TestTextValue"/>
</appSettings>
</configuration>
I have tried using .GetExecutingAssembly() method which I expect to return an assembly of a code that's currently being executed. This didn't work, instead it has returned the assembly of a Windows application.
GetAssembly(type(WCSConfiguration)) has returned a right assembly, however, the configuration file was missing in the bin/debug directory.
I have a feeling that either I'm doing something fundamentally wrong or Microsoft hasn't made this flexible enough. I have also tried to search MSDN for explanation, but this hasn't been documented well IMO.
I have also left COM in bold because I'm not sure whether any config files would be available to COM library at all. Firstly I would like to get other projects to work.
I understand that this is a lot of information. Any help would be greately appreciated. Previously we have chosen to use registry, but this has turned out to be nasty, mainly because access to registry is not available in some scenarios. Additionally we now have multiple versions of the applications and switching between branches is a half an hour job :(
Thank you
Edit:
If I add the dll's config sections to app.config that means that these settings will be available only from that application. Please correct me if I'm wrong. Example that I have provided is a scaled down version. In total there are about ten windows applications, a single MVC project and range of class libraries all of which need to make a use of that configuration.
Configuration settings are mostly connection strings, lookup values that do not belong in the database and few other minor settings. Main concern at this point are the connection strings. There are few minor releases of the application where each release points to a different database.
What I'd like to get out of this is a good workable solution so that it can be posted online and other people who come across the same problem won't spend days of their time.
Morale of the story IMO:
Use both App.config and Web.config to store location of your own configuration file.
Write simple XML serializer to read/write config and DLL for serving the configuration.
COM objects are a long story and were implemented with a "hack", since neither App.config or Web.config are available in COM DLLs.
Note ConfigurationManager.OpenExeConfiguration needs to be passed the filename of the config file, not the executable.
You'll need to append .config to the path of the executable. To get the exe assembly use Assembly.GetEntryAssembly.
If you have configuration settings you want to share across multiple pieces of code that are not all in the same .NET Process, I would suggest:
Put them in their own myStuff.config.
In .NET code use ConfigurationManager.OpenExeConfiguration to open and access myStuff.config.
Non-.NET code will need to use an XML parser to load and read the settings. Unless you configuration structures are very complex this shouldn't be too hard to encapsulate.
Put the path to myStuff.config in the app.config of each application sharing this configuration for .NET applications. (Not non-.NET applications: depends on what works for that application.)
Another approach, where the configuration structure is the same but the settings are per-application would be a custom configuration section.
A couple of general points -- add the dll's config sections to the app.config file rather than relying on the dll's config file to get picked up; and app.config actually gets renamed to .exe.config on build, so you need to make sure a file of that name's available.
Also -- you're not constrained to using the default config loading mechanism to configure your application. You could create your own configuration classes and just use XML serialization to deserialize and configure at will.
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.
I'm writing a class library as an abstraction to use for logging in any application, service, etc. that I write. I'm making it decently robust by making it very configurable to suit my needs for most application/service logging scenarios that I come across.
The config is designed to specify things such as:
What logging level to write
Write to one log file for all levels
Write to separate files per level
Logging cutoff (periodic, app event, byte size restricted)
Log file expiration (delete log files after file age)
Write as flat text or XML
Log file name format specification
Whether to prefix filename with date
Parent app's name
etc, etc, etc...
I've read some other stackoverflow questions regarding configs for DLL assemblies and it causing conflict between the app.config for the hosting assembly/app. I believe that my assembly has just cause to provide a config file.
Is this a good scenario for that occasion? Is it perhaps a better idea to bake my own config into my project so that my logger reads from XML files to retrieve config values?
What you could do is
create a custom configuration section (using e.g. the COnfiguration Section Designer tool)
put your assembly's configuration into a separate MyAssembly.config file
reference that assembly config file from your host app's config:
<configuration>
<configSections>
<section name="YourAssembly"
type="YourAssembly.ConfigSection, YourAssembly" />
</configSections>
<YourAssembly configSource="MyAssembly.config" />
</configuration>
That way, you can "externalize" your configuration into a separate config file which you have only once (in your assembly's project), and any project needing it just needs those settings in its own config file.
Sounds like a custom config section would work well in your case. Many libraries, such as the Enterprise Library do exactly this. Check out the MSDN article about creating one.
The .NET config mechanism is not meant to handle configuration files for DLLs. You should configure your application with appropriate settings and pass them on to the class you are instantiating from the DLL.
It is possible to add settings to a DLL project as you'd usually do for applications. All you then need to do is copy the relevant sections and entries into the application's app.config manually and it will work.
It is, however, still true that there's no point copying the DLL's config file. It will not be read.
Another mechanism is to have a seperate configuration file (*.dll.config) for your assembly. The technique is shown here: http://blog.rodhowarth.com/2009/07/how-to-use-appconfig-file-in-dll-plugin.html
The above, imitate the standard app.config technique for assemblies.
In my opinion the dll configuration reading code should only exist in the corresponding dll and in a seperate class - with single responsibility of reading configuration entries from the *.dll.config. This is a nice way of having configuration file for an assembly in a way similar to the configuration file (app.config) an executable can have.
When I try and use code that makes use of the Enterprise Library Caching Block I get the following error:
The "cachingConfiguration" section is not available in the supplied configuration source.
The section is in my app.config file for that particular assembly though. If I copy the file into the unit test assembly that makes use of the afore mentioned code everything works. Is there any way that I can force it to use the app config that exists in the referenced library so I don't need to duplicate it in every assembly that makes use of it?
Yes.
Select an app.config file to be your master config file (a good choice would be the one in the project of the main application executable).
Now go to your other project (fx. the unit test project). Right-click and select Add Existing Item. Point to the master app.config file and add using the "As link" option:
Add as link http://blog.codevelop.dk/pics/AddAsLink.png
Now you only need to manage one app.config file, and the other projects will 'reference' this file.
Option 2: If you wan't to control what config file the Enterprise Library uses for caching configuration, use:
var fileSource = new FileConfigurationSource(configFilePath);
var factory = new CacheManagerFactory(fileSource);
ICacheManager manager = factory.CreateDefault();
The dll config file that you see in the IDE (if you are using the designer to add settings etc) is largely for convenience. The runtime won't look for it; it wants the file from yourexename.config. Some components provide the facility to specify a separate config file path - I don't know if this is the case for entlib.
Alternatively if you are spawning your own AppDomains you can specify the config file path. And finally some config sections can be referenced in from other files rather than using the file completely (see configSource here) - but in general (and especially for tests) it is easier to just copy the configuration section into the top-level app's config file (or the unit test's config file in this case).