Click here to Skip to main content
Click here to Skip to main content

Creating a Custom Settings Provider

By , 17 Oct 2007
 

Introduction

This article demonstrates how to write a custom Settings Provider to allow you to persist your My.Settings to your own storage system. The example given creates an XML file in the application folder which is ideal for portable applications. It also includes brief details of how to implement storage onto a U3 compliant USB device.

Background

The My.Settings functionality introduced with .NET 2.0 saves a lot of time and repeated effort for developers by providing a common, easy to use, and well thought out method of loading/saving settings. For a standard WinForms application, this works great, separating local and roaming settings automatically and storing them in the Documents and Settings\User\Local Settings\Application Data and Documents and Settings\User\Application Data folder hierarchies, respectively. But, what happens if you haven't got a typical scenario, say you want settings to be stored on a network drive, or you want them to be portable with the application so they can run off a USB device? As with most things in the .NET framework, you can override this default behaviour thankfully. In this case, it's by writing your own Settings Provider. This sounds daunting, but is actually relatively trivial. All you have to do is create a new class that inherits from SettingsProvider and provide the must override ApplicationName property which I just default to the Product Name.

Using the Code

Using a custom settings provider is simple; just include the class within your application, and when viewing the My Project/Settings page, just set the Provider property (defaults to blank) to your provider class name. Note that the Provider property is set for each setting individually; that way, you could keep some items under the default .NET provider model but override a few critical ones to travel with you using this portable provider.

The screenshot below shows exactly where to change this:

Screenshot - CustomSettingsProvider1.jpg

By default, the roaming property is set to false, which for the portable settings provider will mean that the setting is machine specific. For settings like window size/location, this is desired, but for settings you want to be used regardless of machine (in this example, the UserWord), you should set this to true.

Other than that, handle the settings exactly as you would normally do. In the example app, we just get and set them on our Form Load and Closing events.

When you run the application, it tries to load the settings from an XML file named applicationtitle.settings. Since this does not exist to start with, it uses the default values. Upon exiting the application, the settings file is created. If you have a look at it (in the project's bin/debug folder), you'll see it has the following format;

<?xml version="1.0" encoding="utf-8"?>
<Settings>
  <WorkPC>
    <WindowSize>300, 100</WindowSize>
    <WindowLocation>100, 100</WindowLocation>
  </WorkPC>
  <HomePC>
    <WindowSize>300, 200</WindowSize>
    <WindowLocation>300, 300</WindowLocation>
  </HomePC>
  <UserWord>Test</UserWord>
</Settings>

Notice how the settings that have a roaming value of false are enclosed within an element for the current PC name, whilst the roaming setting of UserWord is at the Settings node level, meaning it is used regardless of the PC you are using.

Also included is a U3 specific settings provider. This inherits from PortableSettingsProvider, overriding the GetAppSettingsPath function which, in this case, tries to retrieve a path from an environment variable. If you're happy with the storing of settings within an XML file but just want to change the location (perhaps a common network mapping), then you can use this inheritance technique as well.

Points of Interest

The real guts of the Settings Provider happen in the GetPropertyValues and SetPropertyValues functions. These pass in a collection object of all properties required to be got/set for this provider, which we just iterate round, loading or saving them to our XML document. I have implemented a SettingsXML property which either loads or creates a new XML document with the required root node.

The final point of interest is the IsRoaming function. This looks through the attributes collection of the objects on the property for a type of SettingsManageabilityAttribute. This attribute being present indicates that the IsRoaming property is set to true.

History

  • 18 October 2007 - Initial article.

License

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

About the Author

CodeChimp
Web Developer
United Kingdom United Kingdom
Member
A general purpose analyst programmer working in a small development team for a company in the city.
 
VB has always been my passion and I code both Win forms and web based systems for both work and fun.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
AnswerHaving trouble with Reload() or Reset() not loading new values? Here's the answer!memberQuinxy von Besiex18 Nov '12 - 16:58 
Ugh, so this drove me nuts for a few days. The code provided here in the article and the updated one in the comments DOES NOT support Reload() or Reset(), which means that you can't load values updated by something else accessing the portable settings file (in my case another executable). Not something lots of people are going to do, but nonetheless I need to do it and I was very frustrated and confused about why it doesn't work!
 
The secret is this. The SettingsXML getter only loads the XML settings doc once and after that it just uses the document contents it cached, so of course Reload() can't do anything since it just re-uses the original XML doc contents. The trick is to add the IApplicationSettingsProvider and define Reset() to clear the cached XML doc so reload will reload it:
 
public class PortableSettingsProvider : SettingsProvider, IApplicationSettingsProvider
 
And then define its methods as:
 
public void Reset(SettingsContext context)
{
    _settingsXML = null;
}
 
public SettingsPropertyValue GetPreviousVersion(SettingsContext context, SettingsProperty property)
{
    throw new NotImplementedException("Not supported.");
}
 
public void Upgrade(SettingsContext context, SettingsPropertyCollection properties)
{
    throw new NotImplementedException("Not supported.");
}
 
And now you call Reset() as in:
 
Properties.Settings.Default.Reset();
 
whenever you need the values reloaded from disk (Reset() first does the reset in the settings provider and then a reload).
 
(I do not know if there is an efficient way to cause Reload() to have done this, since the XMLSettings getter is used and doesn't know why it's being called, and I wouldn't want it wastefully reloading the XML from disk.)
QuestionVS 2010memberErik Leo7 Jun '12 - 0:08 
Getting a lot of errors when trying this is VS2012. Any chance for an updated version?
QuestionBad markup in generated XMLmemberEric Legault28 Mar '12 - 18:40 
First off, thanks for the awesome sample! This has saved me a lot of work.   However, I've noticed something weird in the markup in the generated config file: all angle brackets below the machine node get canonicalized (I think that's the term).   E.g.:
 
<?xml version="1.0" encoding="utf-8"?>
<Settings>
   <PRECISION>
      <MyStores>&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;EnabledStores xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
   &lt;ConfiguredEnabledStores&gt;
      &lt;EnabledStore&gt;
         &lt;Enabled&gt;false&lt;/Enabled&gt;
         &lt;Name&gt;Test1&lt;/Name&gt;
      &lt;/EnabledStore&gt;
      &lt;EnabledStore&gt;
         &lt;Enabled&gt;false&lt;/Enabled&gt;
         &lt;Name&gt;Test2&lt;/Name&gt;
      &lt;/EnabledStore&gt;
      &lt;EnabledStore&gt;
         &lt;Enabled&gt;false&lt;/Enabled&gt;
         &lt;Name&gt;Test3&lt;/Name&gt;
      &lt;/EnabledStore&gt;
   &lt;/ConfiguredEnabledStores&gt;
&lt;/EnabledStores&gt;</MyStores>
   </PRECISION>
</Settings>
 
Any ideas?
QuestionGenerates a Form Designer Error and just cant seem to get around it...memberBruceL25 Oct '11 - 9:55 
This code is something I have been looking for for a very long time. I was so excited to get this in place and working, but after doing the work needed my Main form simply will not open. We run Visual Studio 2010 with DevExpress, and no matter what I do (eg, tried all the suggestions posted here) I just keep getting the Form Designer error and I have to go back, remove all the Provider values, and then the form opens again.
 
Am I correct that using this code, I should be able to use the Settings Designer? ...Or is this JUST for runtime type usage?
 
The original post mentions "and provide the must override Application Name property"... Is this already in the code being posted? It appears to be, but am I missing something there?
 
I would REALLY love to get this great piece of code working - the biggest complaint we get from our field guys is how awful the Configuration values are to work with because they can never find them as Microsoft has WAY-over-complicated the whole Configuration and Settings engine. For our needs at least.
 
Bearing in mind that I tried every suggestion posted here just to get that Main form to work, and nothing resolves the issue, any suggestions?
 
Thanks so much either way - this is really great code, just wish I could get it to work.
AnswerRe: Generates a Form Designer Error and just cant seem to get around it...memberaron@versatel.nl18 Feb '13 - 6:37 
Probably you already found a solution for this, since this is an old thread. But to be sure here's your solution:
 
You need to use the full name of the provider type when setting the provider of one setting. The sample in the link you provided set the provider to PortableSettingsProvider, but you need to set to WindowsApplication1.PortableSettingsProvider if your main namespace is WindowsApplication1.
 
Found on Windows DevCenter
http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/f7bacd3b-35f2-4a88-aeb1-111d18a53db0/[^]
GeneralRe: Generates a Form Designer Error and just cant seem to get around it...memberBruceL19 Feb '13 - 5:06 
Aron,
 
Thanks for the reply. I used this code to develop a library that I have used in a few systems. Generally it works very well and has been a helpful bit of code. I named that library "customSettingsProvider" and I include the DLL with these systems. When I do that, I simply set the provider to "CustomSettingsProvider.CustomSettingsProvider" and this works very well.
 
However, there are times, most often with old existing systems that I cannot get this thing to work. I think this is because the Initialize routine doesnt run, or doesnt run correctly - but I wind up with what looks very similar to App.Config in the Bin\Debug folder - NOT the usual settings file this produces.
 
Its not a crisis, but I sure would love to successfully debug that. Otherwise, this is some great code and has been very helpful.
GeneralMy vote of 5memberOneSpeed4 Nov '10 - 19:48 
Clear, concise, accurate
GeneralI get null reference exception when I specify custom settings providermemberruslanv19 Jul '10 - 8:51 
Could you please take a look at this thread?
 
http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/ffc027ef-2579-450b-927d-9792c7610489[^]
QuestionHow to deal with null in propVal.SerializedValuememberbalistof215 Jun '10 - 5:05 
Hi I was wondering if you came accross a null value in the propVal.SerializedValue property. As I have a Settings entry which is of type DateTime it shows me the right value but the SerializedValue property is empty.
 
Chris
QuestionHow to set Custom Provider to just a few settings?membertinatran308 Jun '10 - 17:04 
I have 10 settings. I want to set the first two settings to use CustomSettingsProvider class and the last eight settings to use the default LocalSettingsProvider class. How do I do that?
 
I tried that following but it didn't work correctly:
- Set the Provider properties of the first two settings using IDE as shown in the article. In this case, CustomSettingsProvider didn't get use at all.
- Set the Provider properties of the first two settings using IDE as shown in the article and attribute of the Settings class to use CustomSettingsProvider. CustomProvider was used but the last eight settings were also have CustomSettingsProvider as their provider instead of the default LocalSettingsProvider class.
- Set attribute of Settings class to CustomSettingsProvider. In this case, all ten settings has CustomSettingsProvider as their provider instead of LocalSettingsProvider class.

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 18 Oct 2007
Article Copyright 2007 by CodeChimp
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid