Changing dll settings without re-compiling
Monday, July 13th, 2009 by Pablo RomanoC# settings are a wonderful thing; they provide an easy and powerful way to customize compiled applications by changing data stored in external files.
They work great when they are part of the startup project but - there’s always a but that ends up in a post - when you use them on a referenced project they always take their default value.
After three days of poring over blogs, framework documentation and other resources I concluded that no solution or work-around was readily available, even though the problem seems to be well known.
I tried several approaches, this post will describe the one I consider the best. You can skip the discussion and download the code directly here or keep on reading to find out how it’s done and download it later.
Scenario
I stumbled on this problem while testing the new “multi-function terminal” for the Dot Baires Shopping. The application is deployed in many terminals which communicate with external services providing their identity, for example ‘abc123′, also each machine has its own timeout parameters, for example time to go back to the home screen. These parameters may vary from one machine to the next.
“Hardcoding” the values was obviously not an option, the sole idea of one compilation per station was disturbing. I could, of course, have written a parser and stored these values in an XML, but I already had the Settings feature provided by the framework and I wanted to use it.
How Settings Work
When you add a “Settings” to a project, (I will name it “MySettings” in these example), Visual Studio automatically adds an app.config file, it also keeps synchronized the MySettings.settings file with MySettings.Designer.cs and the app.config, as you can see the default value of the setting is stored in three places.
When the project is compiled a file named ProjectName.exe/dll.config is generated, the .exe.config file has no mystery, you have compiled a solution and the settings are used in the startup project, change this file and you will see the changes in the application.
Settings in a DLL
Well, settings were beautiful so far, but here they get a little tricky - a nice word for buggy.
Let’s imagine you are building a solution that has a Persister, a Credit Card Manager and UI interaction, you want to reuse your Credit Card code in other projects so you put it in a project of its own with its own configuration values in the Settings, probably a Store Id for the transactions and other things . Now you compile the Credit Card project…, great!! the compiler generated a CreditCard.dll.config file which holds the Store Id as we expected!
Well, let’s compile the solution then! Mmm…, but where is the CreditCard.dll.config now??, to make a long story short it’s not there, there is one in the CreditCard project folder bin\debug\, but if you copy it to the directory the solution was build into you will find out the values will still be the default no matter what you do. The reason is the .config files are only used in the startup project.
My approach
After three days reading I couldn’t find a solution I liked.
I like Settings, they provide a good way to save data in files without having to write a parser, also the data are strongly typed and have default values in case the .config is not found.
After all the Settings are a main gear in the .Net Framework, so I started thinking of a work-around.
My approach was simple, if the .dll.config file wasn’t being read I had to add a file of my own, so I thought of the configSource attribute that can be applied to the userSettings, if you want to read more go to http://aspalliance.com/820.
Test solution
Components of the solution
- Winform project “Test” with a form “TestForm”
- Dll project “DllWithSettings” with Settings “MySettings.settings”
- I added a class “SettingsConsumerClass” in the “DllWithSettings” project to access settings dependent values from the winform project “Test”
TestForm.cs
using System.Windows.Forms;
namespace Test
{
public partial class TestForm : Form
{
public TestForm()
{
InitializeComponent();
MessageBox.Show("String Value: " + DllWithSettings.SettingsConsumerClass.StringValue + "nInt Value: " + DllWithSettings.SettingsConsumerClass.IntValue);
Focus();
}
}
}
SettingsConsumerClass.cs
namespace DllWithSettings
{
public static class SettingsConsumerClass
{
private static readonly int _intValue = MySettings.Default.TestValue;
private static readonly string _stringValue = MySettings.Default.AnotherTestValue;
public static int IntValue
{
get
{
return _intValue;
}
}
public static string StringValue
{
get
{
return _stringValue;
}
}
}
}
If you try what we have written so far you’ll see that it compiles, and it also shows the settings, but if you look for the output directory you will see there’s no .config file and if you copy the one generated in the “DllWithSettings” output directory and change it nothing will happen.
Making it work
First I extracted the settings from the app.config and put them in DllWithSettings.config, this means changing the app.config in the “DllWithSettings” project from
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > <section name="DllWithSettings.MySettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" /> </sectionGroup> </configSections> <userSettings> <DllWithSettings.MySettings> <setting name="TestValue" serializeAs="String"> <value>123</value> </setting> <setting name="AnotherTestValue" serializeAs="String"> <value>Compiled</value> </setting> </DllWithSettings.MySettings> </userSettings> </configuration>
to
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > <section name="DllWithSettings.MySettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" /> </sectionGroup> </configSections> <userSettings> <DllWithSettings.MySettings configSource="DllWithSettings.config" /> </userSettings> </configuration>
DllWithSettings.config
<?xml version="1.0" encoding="utf-8" ?> <DllWithSettings.MySettings> <setting name="TestValue" serializeAs="String"> <value>123</value> </setting> <setting name="AnotherTestValue" serializeAs="String"> <value>Compiled</value> </setting> </DllWithSettings.MySettings>
The “Copy to output directory” of this file must be set to “Copy if newer” so it’s available at runtime.
The second and last thing to do is to reference this file in the app.config of the startup project too - if you don’t have an app.config add one.
Because the settings defined in the app.config of the startup project always override others, referencing MySettings.config and making this settings belong to the correct namespace overrides the defaults of “DllWithSettings”, allowing to change them without recompiling.
The app.config in “Test” changes from
<?xml version="1.0" encoding="utf-8" ?> <configuration> </configuration>
to
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > <section name="DllWithSettings.MySettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" /> </sectionGroup> </configSections> <userSettings> <DllWithSettings.MySettings configSource="DllWithSettings.config" /> </userSettings> </configuration>
You can download the source code here.
Well, that’s all, hope you learned something useful, please post if you have any doubts or comments!

September 25th, 2009 at 12:53 pm
Seems like this config files are really confusing to clarify as their behaviour changes from the dev environment to deployment. Apparently a DLL can have its own config file, but once you copy and paste the dll (together with their config file) elsewhere, the whole thing stopped working.
The only solution is to manually merge the app.config files into a single file, which will only be used by the exec. For e.g. myapp.exe will have a myapp.exe.config file that contains all settings for all dlls used by myapp.exe.
I’m using VS 2008.
Kenny Liew
September 25th, 2009 at 1:42 pm
Yes, you are right, but that is a solution, not the only one.
This post explains another one that is more straight-forward, allow changes without re-compiling and doesn’t require any post-build task (like the merge). Try the code and let me know what you think!
October 5th, 2009 at 5:13 pm
Great solution, I almost came close to it, so you saved me time a bit :). Anyway, another aproach to not get “default” values is simply to add your app.config file of the dll project as a linked app.config to the main application, and change access modifier of the settings class in dll to public (available only VS 2008). In that case every change in the settings file is reflected in app.config. You even can have multiple settings combined in one app.config from the different settings files. I came to the idea of creating a settings dll which can be included in various projects. And then configSource comes into play, when you can include only those settings you need, depending on the environment.
October 6th, 2009 at 2:17 pm
Glad you liked it!, your approach is very interesting, didn’t know about the existence of the linked config files, I will try it!
October 13th, 2009 at 7:22 am
Great post, have been looking everywhere for a solution to the problem…
@Rolandas: I would really like to see an example on how to use linked config files. I tried google it and found an element to add to the app.config file. But i didnt get the settings in my linked file to appear in my main settings file.
October 29th, 2009 at 10:13 am
Who can I modify the DllWithSettings.config file and get the new properties values?
Thanks
Nuno
October 29th, 2009 at 4:25 pm
Hi, you only need to change the .config file and restart (close and open) the application.
Try the example and please don’t hesitate to ask again!
January 8th, 2010 at 6:14 pm
The linked file method didn’t seem to work.
Unless a prebuild script is added to copy the web.config over a dummy config file in the main project:
del $(ProjectDir)web.config /F /Q
copy $(ProjectDir)..\\web.config $(ProjectDir)web.config /Y
This will force the deletion of any existing web.config file and copy the dlls config file over it.
Will work even with source control.
I don’t like it as it is confusing though.
February 22nd, 2010 at 1:09 pm
WoW, that is a lot of work for something that should be very simple.
For applications I use the app.config since it is provided, however for DLL’s I have always justed used a simple XML File, and C# makes serializing to/from XML very easy. Basically I just take a simple class with only public Properties and this is what becomes the XML file. I then use a static util class that loads it up in its static constructor. Then you can just make the object available at anytime with the settings needed.
For a DLL I can see why it would care about User/Global settings, or why it should be so convoluted to store external data points for a DLL that change how it works.