Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

Making Application Settings Portable

4.17/5 (18 votes)
9 Feb 2019CPOL4 min read 44.9K   1K  
How to create a custom settings provider for .NET applications

Introduction

This article shows how to store .NET application settings in the application's folder (or any other place) to allow them to be portable together with the app. This is achieved by creating a custom settings provider which handles loading and storing of settings.

An updated version of this implementation with some little additions is hosted on GitHub at https://github.com/bluegrams/SettingsProviders. Another settings provider which attempts to store settings in JSON format can also be found there.

Background

.NET provides an integrated mechanism for storing application and user settings which makes it easy for developers to create and use these settings. To give a brief overview: Settings for Windows Forms (or WPF) generally are divided into two categories: Read- and writeable user-scoped settings stored for every user account and application-scoped which are typically read-only at runtime. Both types are accessed through a settings class derived from ApplicationSettingsBase which provides the settings properties and basic methods for loading and saving.

The actual data however is provided by a class derived from SettingsProvider which handles loading and storing the data. The default settings provider stores user-scoped settings in an XML-like format in the file user.config in the AppData folder of the user. This is quite sufficient for a typical application, but in some scenarios (e.g. a portable application that should not touch the AppData folder), an alternative storage location would be preferable. As the storage location of the default settings provider can't be changed, we must implement our own settings provider. This is not quite complicated as just a few methods have to be implemented. Nevertheless, there are a few tricky points to be considered.

Using the Code

The Standard Way

Applying the portable settings provider to your application settings can simply be done within Visual Studio. To do this, go to the settings designer, select a setting and open its properties page. It contains a Provider field which is empty by default, set this to the name of the provider. Note that you must specify the full name of the class including namespaces, which is Bluegrams.Application.PortableSettingsProvider in this case.

Image 1

It is also noticeable that the settings provider has to be set individually for every settings property on this way. This allows flexibility but it may not be the easiest method especially for large settings files.

The Quick Way

Therefore, this implementation of a portable settings provider provides a simpler method. To make all settings in a settings class portable, just use its ApplyProvider() method like this:

C#
// make the default settings class portable
PortableSettingsProvider.ApplyProvider(Properties.Settings.Default);

The Config File

When applied, the portable settings provider stores the user-scoped settings in a file named portable.config in the application folder. If this file is not existent, the default values are used and a new file is created. The data is serialized in an XML-style format similar to the default settings files:

XML
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <userSettings>
    <Roaming>
      <Bluegrams.Application.WPF.Properties.Settings>
        <Culture></Culture>
      </Bluegrams.Application.WPF.Properties.Settings>
      <TestWpfApp.Properties.Settings>
        <RoamedSetting>Default text</RoamedSetting>
      </TestWpfApp.Properties.Settings>
    </Roaming>
    <PC_MachineName>
      <Bluegrams.Application.WPF.Properties.Settings>
        <Width>640</Width>
        <Height>480</Height>
        <Left>100</Left>
        <Top>100</Top>
      </Bluegrams.Application.WPF.Properties.Settings>
      <TestWpfApp.Properties.Settings>
        <LocalSetting>Default text</LocalSetting>
      </TestWpfApp.Properties.Settings>
    </PC_MachineName>
  </userSettings>
</configuration>

Several points are noticeable. First, the file is divided in a <Roaming> section and a section with the name of the current PC. Properties in the roaming section are the ones which are portable to another machine, whereas all other settings are specific to one machine (settings like window location or size should be found here). To place a setting in the roaming section, just set the Roaming property to true for that setting (see image above).

The settings properties then are further divided into the settings classes they belong to. This allows different classes from different locations to share the same settings file.

Points of Interest

A custom settings provider must only implement three methods, where GetPropertyValues() and SetPropertyValues() are the two important ones. These methods receive a collection of settings properties and perform loading or saving of the XML file. As the provider should only handle user-scoped settings and it must differentiate between roamed and non-roamed settings, the methods IsRoaming() and IsUserScoped() iterate through a property's attributes to check this. The IsRoaming() method searches for the SettingsManageabilityAttribute whereas the IsUserScoped() method indicates whether the UserScopedSettingAttribute is present.

As a third method, Initialize() must be overridden from the base class. Here, it is important to specify a value for the name argument as this argument cannot be left empty.

Next, we make sure the Reload() method works as expected. To achieve this, the settings provider does not cache any loaded XML content on its own but loads the settings from file every time the GetPropertyValues() method is called. This sounds extremely inefficient but the settings class caches the properties itself, so the settings provider only comes into action if the settings really have to be reloaded because, for example, the Reload() method is called.

As a last point of interest, have a look at the Reset() and Upgrade() methods available in every settings class. To provide support for this methods, the settings provider has to implement an interface called IApplicationSettingsProvider. In this implementation, the Reset() method simply deletes the settings file to reset all settings to their default values.

History

  • 2018-11-17: Fixed several bugs in the implementation
  • 2018-04-08: Initial version

License

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