Click here to Skip to main content
15,886,056 members
Articles / Programming Languages / XML

Shared Application Settings in machine.config

Rate me:
Please Sign up or sign in to vote.
4.86/5 (7 votes)
13 Dec 2010CPOL7 min read 52.7K   451   27   6
This article describes how to store application settings in the machine.config file and how to expose these settings as strongly typed properties using .NET’s Application Settings architecture.

Background

Application behavior frequently depends on exogenous parameters, such as a service URI or file paths, that are supplied by a developer or administrator. These inputs must be amenable to quick change without the need to refactor or recompile. A common answer to this requirement is to place such inputs in a configuration file: app.config for Windows applications, or web.config for web applications. When settings are stored in an XML file, an administrator can easily edit them as needed.

This solution works well for a single application. .NET architecture also provides a way for multiple applications to access shared settings. As a simple example of when this may be desirable, suppose you have some functionality that needs to be exposed via a command-line interface, a GUI, and a web app. Since only the interfaces are different but the functionality is the same, there is a good case to pool the settings into one place.

When the applications are on the same machine, their shared settings can be stored in the machine.config file. As you probably already know, you can add an <appSettings> element to a configuration file to contain custom data that your applications need. However, all data in appSettings is stored as strings, and is exposed by the framework as a NameValueCollection, which is suboptimal for a number of reasons. In the next sections, I demonstrate a better solution.

Solution Overview

.NET already has a good alternative to appSettings, and it has a similar name: Application Settings. In contrast to appSettings, application settings are exposed as class properties, which permits them to be strongly typed, easily refactored, and used in bindings. However, by default, application settings are saved to app.config instead of machine.config, and are accessible only within the assembly.

The solution is to move the settings out of app.config into machine.config and make the class that exposes them visible outside the assembly. Multiple applications can then access these settings by simply referencing the assembly.

Step-by-Step Guide

1. Create a New Class Library

For this example, I started with an empty Visual Studio solution and created a new Class Library project, which I named Netrudder, to serve as a base reference for projects in the same namespace.

2. Add Settings

  • Add a new Settings template to the project. I named mine NetrudderSettings.
  • Open the new .settings file. The Settings Designer comes up.
  • Add your settings. Make sure to assign the correct Type, and to change scope from User to Application.
  • Change Access Modifier to Public. This affects the visibility of the class whose properties map to the settings. It is created for us alongside the .settings file.
  • Save the project.

settings1.jpg

Extra Information About the .settings File

The .settings file is just an XML file. By default, Visual Studio opens it in Settings Designer, but you can also open it in the XML Editor by right-clicking the file name in Solution Explorer and choosing "Open With..." -> XML Editor. This is useful if you need to copy and paste settings from another .settings file, which you can't do easily with the Designer.

A Note About Visual Studio Express

The VB version of Visual Studio Express does not provide a Settings template by default. If you don't have one, you can just copy the existing Settings.settings file in Solution Explorer (check "Show All Files" and expand My Project), paste it in the root folder, rename it to something you like, and now you have a second .settings file. You can also just use the existing .settings file. If you do, you will have to change all references to the settings class to its default fully qualified name, which in VB is My.MySettings (preceded by the root namespace).

3. Add the "shortcut" Module

Paste the following code into a new module, substituting your root namespace for my Netrudder:

VB
<Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
Public Module SettingsShortcut
    Public ReadOnly Property Settings() As Netrudder.NetrudderSettings
        Get
            Return Netrudder.NetrudderSettings.Default
        End Get
    End Property
End Module

While this step is not absolutely necessary, it creates a nice shortcut to a synchronized instance of the settings class, effectively contracting Netrudder.NetrudderSettings.Default to a more succinct Netrudder.Settings.

Before we move on, compile the project.

4. Open machine.config

If you are not sure where to find it, follow these steps:

  • Go to File -> Open File.
  • Paste %systemroot%\Microsoft.NET\Framework in the "Object name" field and hit Enter.
  • Open the folder that matches your CLR version. (As a reminder, if your solution is targeting .NET 3.0 or 3.5, your CLR version is 2.0.)
  • The machine.config file is in the CONFIG folder. Find and open it.

5. Move Settings from app.config to machine.config

  • Find the app.config in Solution Explorer and open it.
  • explorer.jpg

  • Locate <configSections> just underneath the root. Copy the <sectionGroup> named "applicationSettings".
  • XML
    <sectionGroup name="applicationSettings">
        <section name="Netrudder.NetrudderSettings" 
              type="System.Configuration.ClientSettingsSection, System, 
                    Version=2.0.0.0, Culture=neutral, 
                    PublicKeyToken=b77a5c561934e089" 
              requirePermission="false" />
    </sectionGroup>
  • Switching to the machine.config tab, paste the copied XML just before the closing </configSections> tag.
  • Back once more in app.config, cut the applicationSettings section:
  • XML
    <applicationSettings>
        <Netrudder.NetrudderSettings>
            <setting name="Copyright" serializeAs="String">
                <value>NetRudder</value>
            </setting>
            <setting name="Year" serializeAs="String">
                <value>2010</value>
            </setting>
            ...
        </Netrudder.NetrudderSettings>
    </applicationSettings>
  • Paste the settings into machine.config just before the </configuration> closing tag.

Notice that I asked you to cut the settings. This is purely for housekeeping purposes. Don't worry - you will not override your settings in machine.config unless you intentionally copy them into the consuming application's configuration file. The application will look in machine.config first, then in its own configuration file (app.config/web.config), and lastly, if it doesn't find the setting in either place, it will use the default value specified in the NetrudderSettings class.

You may have also noticed that the searializeAs attribute of the settings is always "String". Don't try to change it - the correct type is saved with the settings class (NetrudderSettings in the sample).

That's it - all that we really did was copy application settings from app.config to machine.config and change the access modifier of the class to Public, and presto - we can now access our settings from anywhere on the machine.

Accessing Settings from Code

To test the settings, I created a new console project and referenced the NetRudder assembly. You can do the same basic test with a different application type. The following code reads my settings from machine.config and outputs them to the console:

VB
Sub DisplaySettings()
    With Netrudder.Settings
       Console.WriteLine("Copyright {0} {1}", .Year, .Copyright)
       Console.WriteLine("Lat/Lng: {0},{1}", .Lattitude, .Longitude)
    End With
End Sub

It's really as simple as that.

Adding and Editing Settings

To add a setting, open the .settings file and add a new setting the same way you did in step 2. Then repeat steps 4-5.

To change a setting's value, simply edit the setting's value in the machine.config file. As long as the new value is still castable to the type that you specified when you created the setting, a single edit does the trick, and there is no code to refactor and recompile, which is exactly what we set out to accomplish.

Some Additional Pointers

If you have changed the values of your settings in machine.config, and then you open the .settings file in Visual Studio, you will likely get a message box that looks like the snapshot below:

popup.jpg

What to choose? It matters relatively little, but it helps to understand what Visual Studio does.

If you select "Yes", Visual Studio will write out changes to the app.config, duplicating the settings in machine.config. As I pointed out earlier, this is not a problem per se, but you probably want to avoid duplication for maintenance reasons. So, if you let Visual Studio update the .settings file, just remove the duplicate settings from the app.config manually afterwards.

Visual Studio will also update the settings class (NetrudderSettings in the sample), giving each property a new default value. This value is used if no matching setting is found at the settings source, which in our case is the machine.config file. If, in step 5, you copied all the settings correctly into machine.config, then every property has a matching setting in machine.config, and its value will override the default, which is why it doesn't matter very much.

Other Options for Shared Settings

For applications that run on the same machine, placing common settings into machine.config provides a simple, practical solution. But what if your applications reside on different machines? To pick up an earlier example, suppose you want some functionality exposed as a web application and as a command-line utility. You may want the console application to run on a schedule on your workstation, while the web application will reside on a separate IIS machine. In this case, you may want to consider putting your settings in a database and exposing them through a custom settings provider. I demonstrate how to easily do just that with a LINQ to SQL settings provider in the next article, that you can find here: Create a Custom Settings Provider to Share Settings Between Applications.

Further Reading

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
nakkimake9-Dec-10 10:28
nakkimake9-Dec-10 10:28 
GeneralThis is exactly what I need, awesome article! Pin
nakkimake9-Dec-10 10:24
nakkimake9-Dec-10 10:24 
GeneralRe: This is exactly what I need, awesome article! Pin
brownsector10-Dec-10 6:56
brownsector10-Dec-10 6:56 
GeneralRe: This is exactly what I need, awesome article! Pin
nakkimake10-Dec-10 11:22
nakkimake10-Dec-10 11:22 
GeneralRe: This is exactly what I need, awesome article! Pin
Antony Highsky13-Dec-10 9:36
Antony Highsky13-Dec-10 9:36 
GeneralMy vote of 5 Pin
Arlen Navasartian16-Nov-10 12:15
Arlen Navasartian16-Nov-10 12:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.