Centralised settings in C# for multiple programs - c#

I was recently given a heap of programs to maintain and I am trying to find some help in adopting some best practices. They are essentially three independant softwares which use a common DLL to manage a series of settings the apps all share. The DLL works this way: it swaps the user settings file (XML file buried deep in the user's configurations folder in Windows), with a fix file, specified by a hardcoded (egad!) path.
The rationale behind keeping it as user settings and not app settings is that the DLL can be found in several locations (one for each app that will use it), and so the user settings file is common (if all copies of the DLL are the same compile), whereas by using application settings there would be as many app.config files as there are copies of the DLL.
I'm trying to conceive of a better way to centralise these configurations and end the senseless file swapping. One approach (actually, most likely the best approach) would be to redesign all 3 apps so they all use a central dll with its own "app.config". Are there other more recommendable venues?

Have you considered using the Windows Registry? We all hate it, but maybe it's the best option in this case as it is centralized and you could share settings easily across applications.
EDIT: If you don't like the Registry (and I don't blame you for it), you can create an XML or some other configuration file in a directory under the Application Data special folder. This is how this is done these days as far as I know.
string appData = Environment.GetFolderPath(
Environment.SpecialFolder.LocalApplicationData));
string folder = "MyApplicationName";
string fileName = "settings.xml";
string path = Path.Combine(Path.Combine(appData, folder), fileName);

For this precise problem, if it's a .Net DLL, you could use the GAC, this would centralise your DLL. All software would know where they could access this DLL. And in this way, you could have less refactoring to do.
This is only a patch for this problem only. I would not recommend this, for new developpement.
GAC in Wikipedia

You can use settings in a common file - most likely stored under AppData in the users settings folder
The advantage here is that you do not have to modify any code whatsoever.
The application would store its settings in its normal config file and refer to the common file for the dll settings:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings file="commondll.config">
<add key="KeyToOverride" value="Original" />
<add key="KeyToNotOverride" value="Standard" />
</appSettings>
</configuration>
Then in the common file commondll.config:
<appSettings>
<add key="KeyToOverride" value="Overridden" />
<add key="KeyToBeAdded" value="EntirelyNew" />
</appSettings>

Perhaps this solution that shares configuration settings between an ASP.NET app and Console app will contain useful information.

Related

C# App.config vs Settings File

This may sound like a trivial question, however I have looked over the web briefly and what I found was that app.config is basically an older mechanism for storing Application key/pairs of data for the application.
What I want to know is there any reason we (as .NET developers) would opt to use app.config over a Settings file ?
-Can someone please provide some pros and cons on both so we can use them properly.
thanks again
App.config for desktop applications and Web.config for web applications are part of .NET configuration system. Primarily they are used to control .NET framework settings in respect to our application. These are such configuration settings as substitutions of versions of assemblies (section <assemblyBinding>), substitution of .NET framework version (<startup>) etc. (see msdn for the full app.config schema.) One section is dedicated for custom settings of application developers (<appSettings>). There is also a possibility to create custom sections. So, when we need to store settings we can either piggy-back on the app.config or create our own separate configuration files.
Here are pros and contras of using app.config:
Pro: There is already a standard API in .NET to read settings from appSettings section. If you only need just a couple of config settings, it is much easier to use this ready API than to develop and test your own class to read your config files. Also, app.config file is already included in VS project for you.
Pro: There is a standard hierarchy of machine.config/app.config. If you plan such settings that can be set machine-wide and overridden or left as-is for individual applications, you should use app.config.
Pro/Con: App.config is cached in run-time. If you anticipate updates of it while your application is running, you need to specifically request refresh of certain section of config file. For web.config the web app is automatically restarted when something is changed in the file. This is quite convenient.
Con: app.config is stored in the same directory as your .exe file. Normally it will be in a subfolder of C:\Program Files. This directory is extra protected in Windows 7 from writing. You need to be member of Administrators group to write there and if your UAC (User Access Control) level in Control Panel is not set to 0 (which normally is not), you will be asked by the OS to confirm writing to c:\Program Files. So, users without Administrator rights will not be able to change configuration in app.config. Same goes for changing your settings programmatically: your application will get exception when attempts to write app.config if it runs not under an admin user on Windows 7. Your own config files usually go to C:\ProgramData\ or c:\Users subfolder (on Windows 7). These locations are friendlier to writing by users or programs.
Con: If user edited your app.config file and accidentally corrupted it, the whole application will not start with some obscure error message. If your separate config file is corrupted, you will be able to provide more detailed error message.
In conclusion: app.config gives you easier (faster development) approach, mostly suitable for read-only settings. Custom settings file gives you more freedom (where to store file, validation/error handling, more flexibility with its schema) but requires more work during development.
You have it backwards, the settings file (or ini file as they were originally called) was the mechanism used to hold application settings (key/value pairs) prior to Windows 95. With the release of Windows 95 it was recommended that application settings be moved into the Windows Registry (which proved problematic since if you screwed up your registry your Windows may no longer be able to start).
The .config file came into play with .Net. The XML format allows more dynamic and complex settings configurations than simple key/value pairs.
The modern user/settings file is an XML extension of the .config file (settings that can override certain settings in the .config under specific conditions).

How to specify a config file with path?

I would like to setup one web.config file for my solution. How do I specify the path of the config file I am using?
Here is how you can specify new app setting in your web.config file.
<appSettings>
<add key="LoggingDir" value="C:\\Logs\\"/>
<add key="environment" value="test"/>
<add key="smtp.server" value="incoming.ABank.com"/>
</appSettings>
And you can access in your code by
private static String logDirectory = ConfigurationManager.AppSettings["LoggingDir"].ToString();
private static String MailServer= ConfigurationManager.AppSettings["smtp.server"].ToString();
I prefer all my app or environmental settings in a separate file when I have lot of them. You can do that by
<appSettings configSource="env\ApplicationSettings.config"/>
and then write above <appSettings> </appSettings> section in ApplicationSettings.config file.
If you're creating an MVC application, then generally you can access your configuration file (web.config, in the root of the project) using ConfigurationManager:
string sConnectionString = ConfigurationManager.ConnectionStrings["SqlServer"].ConnectionString;
You could try loading a different configuration file using:
ConfigurationManager.OpenExeConfiguration()
Here's a link to the MSDN documentation for the ConfigurationManager class:
http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.aspx - specifically, there's some information included there about the class's intended usage and operation.
Hope that helps,
Cheers!
Not knowing what your projets look like I'm going to go out on a limb here.
Just an FYI, in IIS there will be inheritance that may solve your issues, just be sure to setup your apps for debugging in IIS in the same folder structure.
If you have multiple libraries, you dont need config files for those libs (app.config), so what are you trying to to do eliminate multiple config files? Do you have multiple web sites? If you only have a single site and other class library projects, you won't beed other config files as they won't be used at runtime anyways. If you have multiple web sites, then consider inheritance.
10 things asp.net developers should know about web.config inheritance and overrides

How can I make a DLL ApplicationSettings class which reads from library.dll.config?

I'm creating a plug-in for another application as a DLL, which needs to have settings that can be configured without recompiling the DLL. I created a settings class through Visual Studio as I usually do with application projects. When I build my project a libraryname.dll.config file is created and copied to the output directly.
But, as may other people have already found and written about, this file is never used. Instead if I want to modify these DLL settings I need to merge the settings into the settings file for whatever application that is using the DLL.
The problem I have with this is the calling application is not my application, so I'd rather the configuration of my plug-in live with the rest of my files for my plug-in.
In the past I've used System.Configuration.ConfigurationManager.OpenExeConfiguration() to read a settings file for the DLL like this.
public static string GetSettingValue(string key)
{
string assemblyPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
var config = ConfigurationManager.OpenExeConfiguration(assemblyPath);
var keyVal = config.AppSettings.Settings[key]
return keyVal.Value;
}
Which would read from a settings file like this
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="URL" value="http://www.acme.com" />
<add key="EnableAdmin" value="False" />
</appSettings>
</configuration>
However, I really like newer type safe ApplicationSettings class that is created by visual studio rather then then using <appSettings> which can only store strings.
So what I'm wondering is if there is some way I could override a method or two in the ApplicationSettings class created by visual studio to get it to read from the DLL config file by default? It's not really clear to me exactly where it's being determined which config file should be read.
You can try to merge the applicationsettings file in the calling application. This SO thread explains it pretty well.
How to load a separate Application Settings file dynamically and merge with current settings?
If you do not want to mess with editing the calling application, you can just use the Configuration class like you are doing. Here's another example. I've used this approach when I needed to call a WCF service through COM.
http://www.twisted-bits.com/2012/04/use-a-net-configuration-file-with-a-class-library-dll/
Copy the applicable section to the web.config of the main site or app.config of the main executable, then ConfigurationManager.AppSettings["URL"] works just fine.

What is the best way to store/set configuration settings for a C# application?

I have some values that I want to be able to set, and the application to load them from some kind of file.
The only concept I can think of, is a simple txt file, that might have the following lines:
DatabaseName = "DB1/test"
DatabasePassword = "password"
Development = "true"
but im thinking it should be in some kind of config file? Plus reading a txt file for these values isnt exactly tidy code. It would be nice if i could get the database name by just saying in my application:
configfile.DatabaseName
Thanks,
Paul
You really should be using the built in Application Settings
You can directly access simple settings using the ConfigurationManager
ConfigurationManager.AppSettings["MySetting"] = "SomeStuff";
var mySetting = ConfigurationManager.AppSettings["MySetting"];
There is also direct access to your Connection Strings using the ConfigurationManager
var conn = ConfigurationManager.ConnectionStrings["DevSqlServer"];
All this is stored in XML files, and by default your *.config files.
To Answer Doomsknight's question from the comments
Configuration settings can be done a number of ways, but by default, they are stored in two places.
Application Level Settings are stored in a configuration file.
For executable programs this file is located in the same directory as the .exe and is named after the assembly, or executable.
Example: MyAssembly.config, Another.Assembly.config
For web applications, the settings are stored in the web.config file (usually) located in the root directory of the web application. These are applied hierarchically and one can be located at each directory level of the Web Application.
Example: MySite\web.config, MySite\SubDirectory\web.config
User Scoped Settings are stored in the user profile
Example: C:\Documents and Settings\USERNAME\Local Settings\Application Data\ApplicationName
Connection Strings are stored in the <connectionStrings></connectionStrings> section in your config file.
<connectionStrings>
<clear />
<add name="Name"
providerName="System.Data.ProviderName"
connectionString="Valid Connection String;" />
</connectionStrings>
These settings can easily be modified directly in the config file, but without writing some code to automatically refresh sections of the config file (which is possible), an application restart is typically needed.
I hope this helps out.
.NET has a configuration platform built into it. Just add an app.config file to your project and use the ConfigurationManager library to access the values.

Can we share some contents of App.config between projects?

I have two independent projects in my Visual Studio 2008 solution. Both has its own App.config. But in one project, I need one or two properties defined in another project's App.config. Is it possible to share part of the App.config contents from other project?
Yes - of course. Any configuration section can be "externalized" - e.g.:
<appSettings configSource="AppSettings.DEV.config" />
<connectionStrings configSource="MyConnection.config" />
or
<system.net>
<mailSettings>
<smtp configSource="smtp.TEST.config" />
vs.
<system.net>
<mailSettings>
<smtp configSource="smtp.PROD.config" />
Any configuration section can be put into a separate file that can be shared between projects - but no configuration section groups, and unfortunately, it's sometimes a bit tricky to know which is which.
Also, in some cases, Visual Studio will complain (using red wavy underlines) that the "configSource" supposedly isn't valid - but it is - it's defined on the ConfigurationSection object in the .NET config system.
UPDATE:
another feature that hardly enough developers seem to know and use is the ability in Visual Studio to add existing files from a different project as a link:
With this, you can add links to files into your local project, and they'll always be kept up to date. Great productivity booster if you need to do some file-level sharing (like for common configuration files or such)!
Try this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings file="PROD.config">
<add key="common.Currency" value="GBP" />
</appSettings>
</configuration>
Only the "running" app.config is used, but you can go external like marc_s says.
You can also create a .Settings file that's "shared". Go to the "shared" project properties, the Settings tab on the left, create a setting with Application scope, and set the Access Modifier on top to Public. In your other project you can then use ClassLibrary1.Properties.Settings.Default.SettingName to access it. It will be strongly typed, but you may need it at compile time.
Something I like to do, especially when trying to coordinate ServiceModel elements between libraries and tests is to use configSource to fragment the config in the target library and simply link/copy always the fragments in my test projects.
That way I only maintain in one location.
You could take it one step farther and simply have a common directory in the solution and link the fragments in all projects.
In that situation, I would think using a Database to store some configuration data would be ideal. Each app does its own thing, but they look to a shared database to get those common pieces of information.
EDIT: I spoke too soon! Looks like both the OP and I learned something about config files =D

Categories