Exe, Dll assemblies and their config file applicationSettings group section.


The background

I am reading articles, forum posts about applicationSettings for almost a week now.

In almost every thread there is someone that appears to have correctly pointed out that when deployed, class libraries cannot have config files as executables do. I mean you can always have the file there ClassLibrary.dll.config, but it won’t make any difference if you just copied it from the output folder of the class library project into the folder where the application was deployed.

The application’s code will not be able to read any settings from that file (unless some modification are made to both the exe and the dll’s config files).

The same people say, that to use those settings that you happen to have created at design time for the class library, you have to merge somehow its applicationSettings group section into the deployed application.exe.config configuration file of the application that host/consumes the dll. I have yet to see a clear example of how to do it.

However, you can access the class library’s settings you had configured at the last compilation without merging its applicationSettings group section into the executable’s config file. All the settings created in the class library during design exist as properties of the Settings class from the My namespace. Because they are decorated with a[DefaultValueAttribute] these properties will always return a default value even though there is no setting present in the configuration file. If a setting existed, that specifies other value it will override the default one.

So, in other words, you can merge the dll’s settings into the exe’s config file, but you don’t need to, unless you want to provide the user with a way to override the default values – the ones that are specified using the [DefaultValueAttribute] hard coded in the assembly.

Now, you listening to me as I keep talking about the merging of the class library’s applicationSettings group section.
How is that done exactly?.
Where do I copy the settings?
Do I just grab the setting elements and stick them in the exe’s configuration file in the applicationSettings group section?
I could not find a practical example on any forum and I just assumed that this is how it should be done. While developing my solution was not that obvious that I am wrong. The truth came out only when I deployed my application at the client. The application instead of using the newly configured values was constantly defaulting back to the setting values I specified during design at the last compilation.

So, let’s say that I want to provide the user with a configuration file, where he could change setting values and they actually stick. I couldn’t find anything specific on MSDN so anybody who knows any material, please let me know. What I am presenting you in the next lines I discovered by trial and error.

Anyway, let us use a very simple, practical example. Let’s use VB.NET

1. Create a Class Library project called ClassLibrary.
2. Click on the Solution Explorer’s toolbar on Showing all files button
3. Expand MyProject and double click Settings.settings.
4. Add a setting called Message, application scoped whose value is “Hello!”.
5. Create a property in Class1.vb (the automatically added class)

image
6. Create a VB WinForms project and call it WinForm.
7. Add a reference to the ClassLibrary project.
8. Add a button to the already created Form1 and double click on it.
9. Add the some code to the the Button1_Click handler. Should look like this.

image

10. Have the WinForm project “Set as Startup project”

Now, while in the IDE everything works beautifully. Run the solution and you’ll get the expected Hello! when you press the button. If you go and change the setting in the app.config of the library to say “Good bye!” and you run the solution again you get a “Good bye!”

However, what we want to do is to simulate a run outside the development environment.

1. Right click on the WinForm project and chose “Open in Explorer”.
2. Get to the Debug folder. Note that there’s no WinForm.exe.config file yet. Let’s create one quickly.
3. Switch back to VS and while the WinForm project is selected click to Show All Files.
4. Expand MyProject, open Settings.settings, create a setting “A” with value “A”(doesn’t matter what) and save.

There we go, an App.config was created and if I build this solution, the Debug folder will copy it to a WinForm.exe.config.

So far we have two configuration files in the output folders of each project:

ClassLibrary.dll.config
image

into the WinForm’s config

WinForm.exe.config
image

The question is what and how do we merge the ClassLibrary.dll.config into WinForm.exe.config? If we use the Settings designer that we can invoke by double clicking the Settings.settings file and add the Message setting into the WinForm.exe.config it will not work. Not even when ran from the IDE.

WinForm/Settings.settings

image

The message box will display the default value of the Message property – the one persisted in the ClassLibrary assembly.

First Method

However, if we modify the Winform project’s app.config, by basically copying the section definition and then the whole section itself from the app.config of the ClassLibrary project to their corresponding places in the WinForm project’s app.config, and then compile we obtain a Winform.exe.config that must look like this.

WinForm.exe.config

image

Notice that as we did not have any relevant settings in the WinForm project itself we got rid of the section definition and the settings we added previously.

An unfortunate thing is that the Settings designer when invoked again will pick up this setting and import it but it will save it back to the app.config in the <WinForm.My.MySettings> section if you answer yes to save the app.config changes when asked. This won’t harm unless there’s somehow code in the WinForm assembly that uses a property in My.Settings called Message. If it does annoy you, you’ll have to manually delete it and refrain from saving changes that the Settings designer might want to apply to app.config.

Second Method

If for various reasons you want to keep the configuration in two separate file – maybe you grew fond of the ClassLibrary.dll.config name – you can modify the WinForm project’s app.config to look like:

WinForm.exe.config

image

and copy the ClassLibrary.dll.config from the output folder of the ClassLibrary project to the output folder of the WinForm project after you removed some parts and it looks like this.

ClassLibrary.dll.config

image

Advertisements

6 thoughts on “Exe, Dll assemblies and their config file applicationSettings group section.

  1. I hope this is not an obvious question, but I want to accomplish exactly the oppposite: writing some values in my main project (the winform.exe project in my solution) and then retrieving them if and when necessary in a class library (i.e. a dll-project in my solution) .

    How do I accomplish that? I suppose it will not work if I just copy the whole “Main” is the name of my .exe-project into the config file of the dll-project because: how will I write the correct values to it?

    Thanks in advance

    1. I don’t exactly understand what you want to do but I’ll answer to what I think you meant.

      Application settings (and I mean settings of scope Application ) are read-only so you cannot modify them on disk.
      If you want settings which you can read, modify and then write back so you can read back the latest value at a later time then you have to use User settings. In the same Settings tab of the project properties you will have to select the User scope for you settings.
      The mechanism of moving those user settings from the dll’s app.config to the executable that will use the dll is exactly the same as for Application settings.
      you read from
      someVariable = global::Main.Properties.Settings.Default.yoursetting1
      you write back to it
      global::Main.Properties.Settings.Default.yoursetting1 = someVariable
      and then save
      Main.Properties.Settings.Default.Save()

      If it is not what you wanted try to be more specific in what you try to accomplish and I’ll do my best to answer.

      1. Thanks very much for your reply. What I’m trying to accomplish is this:
        step 1: my .exe writes some values to the app.config (the project is actually called “Main”). I checked this and it works and I can retrieve them as long as I try to do it in a code-file somewhere within my Main-project. (BTW I choose the User scope, good to know that it was the right choice)
        step 2: In one of my dll’s I have to retrieve those values, however there’s no way I can reach them, the code: “Global::Main.My.Settings.someVariable” works in my Main-project (actually just “My.Settings” will do) but not in any of my dll-projects. If I type “Global.” then the code completion shows me all of the dll-projects and other dll’s I have references to but nothing that’s in my Main-project (and obvious;y I cannot set a reference to the Main-project).

        Unfortunately it is not possible to reverse the sequence (i.e. let the dll write those values to the config-file and retrieve them in my Main-project)

        Thanks again for your very quick reply!

  2. Hm, you cannot access dll’s settings from Main and Main’s settings from the dll. The purpose of merging the dll setings into the main.exe.config is only to make the settings available to external modification and further to the dll at runtime, otherwise the dll will use the setting values stored inside the dll at compile time.

    What you want to do you’ll have to do it in a different way:
    1. Either find a way to pass arround those values you are interested between code executing in Main and code executing in the dll. Aggregate them in an object and pass them around as a parameter.
    2. Create your own settings file. Xml format is not a bad choice. With LINQ to XML it’s a pleasure to work with XML filed. Ini file is good too though there’s no support in .NET (though, you can find .Net wrappers for the Win32 API methods do do it). You’ll be able to access that file as you please from any code.

    Cheers.

    1. Hi,dude. I come up with exactly the same problem as you did. Although the appsettings can solve all the problems, I’m still willing to use applicationsettings which has many advantages. Have you found another way to do this other than LINQ to XML? Thanks in advance.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s