Easily Save and Retrieve Application and User Settings in VB.NET or C# Apps

 

We used to save our application or user settings in an INI file (dark ages) or more recently in XML files using our own code or classes borrowed from other developers. But applications built with the .NET framework using Visual Studio can take advantage of built-in tools to simplify or speed up access and saving of runtime values. Once common example is saving database connection string information in a configuration file so that it may be changed without need to recompile the application.

Here are some simple examples in VB.NET. C# code uses a slightly different syntax the concepts are similar. The following examples are using Visual Studio 2008 and VB.NET.

The Basics

Each value you want to use in your application is defined as simple name=value pairs and saved in special XML files. You also define a data type such as string, integer, date, even special types such as connection string. You also choose  the scope of the value. Only two possible scopes are available:

  • Application – is read-only at runtime; you can edit a value and have the app use without recompiling.
  • User – is read / write at runtime; values are saved at the Windows user account level and good for user prefs.
  • If you need the application so save the value at runtime such as a user preference, then choose User as your scope, otherwise you would choose Application as the scope.

    Define Your Values in Visual Studio
    Go to your project properties, then click the settings tab on the left. There you can define one or more values to be used by your application. For each value you will choose the data type, scope and a default value. These values will be saved in a file named app.config in your project folder and in a file named {yourappname.exe}.config in output folders after builds such as \bin\Debug\ if building in debug mode.

SNAGHTML14c99224

 

In you VB.NET code, you can access values defined above using syntax like this.

TextBox1_Subject.Text = My.Settings.Subject
TextBox_FromAddress.Text = My.Settings.FromAddress
TextBox_FromName.Text = My.Settings.FromName

If the value is defined with a scope of User, then you can save the value back to an XML file for later retrieval. Below, the code checks for a value in a textbox an then assigns the value to the Settings object which will be later saved.

If TextBox1_Subject.Text.Trim.Length > 0 Then
    My.Settings.Subject = TextBox1_Subject.Text.Trim
End If

Note that the values in the Settings object are not actually saved until…

  • You issue a My.Settings.Save() method call.. or…
  • You set a project level attribute to save the value when application exits (either in VS or programmatically).

The project level attribute mentioned above is typically already set in a new project. In VS 2008, go back to your project properties and click the tab laSNAGHTML1529810abled Application. There you will see the checkbox that controls this setting (see image). When this value is checked, any User scoped values you have set back to the Settings object will be automatically saved. You might think these value are saved back to the app.config file or the {yourappname.exe}.config files mentioned previously but unfortunately no as that would be too easy. Because they are scoped as User, the values are stored in a new XML file created below the C:\Users\{username}\AppData\ folder and named user.config. For example, my file was created at the following location: C:\Users\don\AppData\Local\Microsoft\EmailSenderNet.vshost.exe_Url_layp1zjs3efmh3nnxgs3wj0if0kd3vz0\1.0.0.0\user.config.  If different users login and use your application, each user can maintain their own separate and unique values making them perfect for user specific preferences.

Another example of the path is this…

C:\Documents and Settings\[username]\Local Settings\Application Data\[AssemblyCompanyName]\[NameOfProject].[SomeLongUniqueString]\[AssemblyVersion]\user.config.

Note that the Assembly Version is the last folder in the path. This means that when you change the assembly version of your application, your User scoped values will be saved in a completely new user.config file. This is actually clever and ensures that each version of your application does not clash or overwrite values from a previous version.

So what happens to the values in the previous app.config and {yourappname.exe}.config files in the output folders? They are really just default values that your application can access at runtime if needed. The app.config is used directly by VS 2008 and updated when you edit the values in the VS project properties settings pane. The {yourappname.exe}.config files in the output folders are copies that can be distributed with your EXE in the same folder.

But remember that when you deploy the EXE, the only values that your application will read from the {yourappname.exe}.config file are Application scoped values. Any User scoped values will be read from the user.config mentioned above.

Synchronize Often

If you been able get this far without falling asleep, you have probably pondered the concept that with so many files holding the same data that things could get out of sync. Or perhaps you are one of the many developers who gave up on using the app.config file because it never seemed to work or would pull up the incorrect values when accessing them in code. Well the reason is because they do get out of sync. And to remedy that problem, Microsoft provided a Synchronize button in the Visual Studio Settings pane as well as programmatic controls. This button will sync the config files and delete and create new user.config files if you have any User scoped values.

The tip here is use the Synchronize button anytime you change the values in the Visual Studio Settings pane.

Summary

While far from perfect and a bit overly complicated, Visual Studio and the .NET framework offer an a quick and easy option for storing and accessing data for your application. They offer tremendous power and flexibility. For example, you can add customized settings files to your project for management of settings in different groups. This allows you to save settings for a group or subset of values in separate files which can save saving and loading time.

For example you can add a special MySettings.settings file to your project. The Settings Designer first searches for the Settings.settings file (default file) that the project system creates Settings.settings is located in the My Project folder for Visual Basic projects and in the Properties folder for Visual C# projects. The Project Designer then searches for other settings files in the project’s root folder. Therefore, you should put your custom settings file there. If you add a .settings file elsewhere in your project, the Project Designer will not be able to locate it.

Well I hope this helps. If you don’t already have a custom class for managing application values or if you just need something fast and easy for a simple utility app, then give the built-in options a try. If you can take the time to read and understand the basics, you will be glad you did.

Comments

  1. Hi Don,

    I was searching for a way to have the user.config file get read/written from/to the EXE’s root folder and found your article which helped me to “see” why that would be a bad idea (“user” preferences). Thanks for this demystifying article! What a blessing! Thank you!

    Kind regards – Fred

  2. Nice article. I’ve been googling and this is the clearest article I’ve come across regarding this subject. What I can’t find out is how the application scope settings are handled when the program is deployed. This is where I keep my connection string, but it seems that it’s not necessary to deploy the {yourappname.exe}.config. Do you know if the connection string is stored somewhere on the user’s computer like the user.config file or if it’s embedded (and hidden) in the exe?

    Thanks,
    Paul

    • Thanks Paul,

      Application-scoped settings are stored in either the machine.config or app.exe.config files. Machine.config is always read-only, while app.exe.config is restricted to read-only for most applications. In other words it really is a read-only (default) setting. Any read-write settings typically require storage in user-scoped settings such as the user.config where user is the user name of the person currently running the app. Default settings can be applied there as well using the DefaultSettingsValueAttribute and values are always updatable by that user.

      User-scoped settings can be stored in app.exe.config files, in which case they are treated as static defaults.

      HTH

  3. Thanks for the reply Don,

    What I am mostly concerned about is deploying my winforms app and keeping the connection string hidden. I can’t protect it using ProtectSection at runtime in app.config as that’s read-only, the other option is to set it as a user setting. I was just wondering if it was actually hidden away in the exe when the app.exe.config file is not deployed or stored on the users computer somewhere.

    Paul

    • Paul – you may want to consider just saving your connection strings in your own file using your own encrypt/decrypt routines. You can just save the file alongside your exe. Sometimes it is easier to create your own solution…simple is always good. Remember the good ole INI files? :)

    • dave friedman says:

      we store our connectionstrings in the .exe.config but we encrypt them with our own private encryption routine. we then run the connectionstring value through your decrypter before using it to establish the db connection

  4. Yeh, simple is always good. I just thought that VB.NET would simply take care of it.
    Ahh the old INI files, they still live on in some places.

    Cheers,
    Paul

  5. after i use this setting in my project..
    im getting 18 messages after debug

    Message 1 Could not find schema information for the element ‘userSettings’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 30 6 QuizViaSMS
    Message 2 Could not find schema information for the element ‘QuizViaSMS.My.MySettings’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 31 10 QuizViaSMS
    Message 3 Could not find schema information for the element ‘setting’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 32 14 QuizViaSMS
    Message 4 Could not find schema information for the attribute ‘name’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 32 22 QuizViaSMS
    Message 5 Could not find schema information for the attribute ‘serializeAs’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 32 36 QuizViaSMS
    Message 6 Could not find schema information for the element ‘value’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 33 18 QuizViaSMS
    Message 7 Could not find schema information for the element ‘setting’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 35 14 QuizViaSMS
    Message 8 Could not find schema information for the attribute ‘name’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 35 22 QuizViaSMS
    Message 9 Could not find schema information for the attribute ‘serializeAs’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 35 32 QuizViaSMS
    Message 10 Could not find schema information for the element ‘value’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 36 18 QuizViaSMS
    Message 11 Could not find schema information for the element ‘setting’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 38 14 QuizViaSMS
    Message 12 Could not find schema information for the attribute ‘name’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 38 22 QuizViaSMS
    Message 13 Could not find schema information for the attribute ‘serializeAs’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 38 38 QuizViaSMS
    Message 14 Could not find schema information for the element ‘value’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 39 18 QuizViaSMS
    Message 15 Could not find schema information for the element ‘setting’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 41 14 QuizViaSMS
    Message 16 Could not find schema information for the attribute ‘name’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 41 22 QuizViaSMS
    Message 17 Could not find schema information for the attribute ‘serializeAs’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 41 38 QuizViaSMS
    Message 18 Could not find schema information for the element ‘value’. C:\bengkel 2\QuizViaSMS\QuizViaSMS\app.config 42 18 QuizViaSMS

    but my project can run.. how can i solve this messages ??

    • Sauce,

      Sorry but I really do not know. This could have many causes. I suggest removing the setting and see if this goes away. Then try adding again. If you still get this, check that VS has full permissions and can create/write to the files it needs to. Also use Google and search using the error messages above. It may take some time but you will find clues as the source of the problem. Sorry I could not be of more help.

  6. “Note that the Assembly Version is the last folder in the path. This means that when you change the assembly version of your application, your User scoped values will be saved in a completely new user.config file. This is actually clever and ensures that each version of your application does not clash or overwrite values from a previous version.”

    Actually it’s not that clever, because when you release even a minor update of your application (eg. 2.0.0 ->2.0.1) which is often 100% compatible with previous version, you loose all user settings. Is there any way to avoid that?

    “So what happens to the values in the previous app.config and {yourappname.exe}.config files in the output folders? They are really just default values that your application can access at runtime if needed. ”

    What does “if needed” means? That it has to be done manually in the code? If so, how can this be done?

    • Adam, Sorry I completely missed your comment (approval) – sorry about that. You raise an excellent questions. Let me review this to ensure I give you a correct answer. I have not looked at this in quite a while.

  7. Adam raises a very good point: when you release any minor update, all the user’s settings are lost. This strikes me as a huge oversight on the part of Microsoft.

  8. A very nice and clear article indeed. When an .EXE is installed for a second or more time does it read from the user.config or from the App.config/appName.exe. I am asking because at that stage the user.config file already exists. I got this puzzle in this example. I set the of NewInstallation to True. Then after installation, the value is set to False and saved, sothat when the app runs it always detect a False value for NewInstalltion. However, wwhen I install the project it does detect NewInstallation to be True on the fiirst installation. When you remove the app and re-install, it always detect a False value for NewInstallation and therefore crashes. It seems to me that on subsequent installations, the .EXE file no longer reads from the App.config, but from the user.config, which unfortunately has been updated. Please explain this puzzle. If this is the case, one has to delete the user.config file before doing any subsequent installations. If this is the only solution, how then does one delete the user.config file? Thanks for clarifying this for me. Mike

  9. Mike – Reinstalling should not change the method your application uses to retrieve settings or cause the errors you are experiencing. However, I have not tested this before and am very intrigued by your findings. Unfortunately I do not have time at the moment to research your question but would appreciate you posting again should you learn more about this.

    To be honest, I often bypass Microsoft’s approach to saving data in config files because most of my apps only need to use application level settings. User settings in a corporate context for me would typically be stored in a database table. So I often revert to simpler, more straightforward techniques such as:

    1) Create a datatable to hold the settings, then save as and retrieve as xml since this is built right into the datatable methods. Be sure you save with schema such as ….

    dt.WriteXml(Path.Combine(sAppPath, “myappdatafile.xml”), XmlWriteMode.WriteSchema)

    The sAppPath can be obtained with something like …

    sAppPath = My.Application.Info.DirectoryPath

    Datatables are great because you can easily loop through the rows, have as many values per row as needed and even pass single rows to methods as a DataRow.

    2) Use the old tried and true INI file approach such as a simple text file with Name=Value pairs on each line. You can retrieve this file into an array of strings with single line such as….

    Dim myappdata() As String = File.ReadAllLines(sDataFilePath)

    Then loop through the array and split each line at the = character and store into a hashtable, list or object array. This is so easy to read and write to. Microsoft wanted to create a generic and universal approach to saving data and it does work but can often require much time to learn all the nuances. But if your needs are simple, then designing your own approach that you have complete control over.

  10. Good article for programmer…. It is very helpfull

  11. To overcome the problem of losing all settings when updating the software you can use the My.Settings.Upgrade which reloads User settings from a previous version.

    I added a User setting entitled “ShouldUpgrade” and “Imports System.Configuration” to my application.

    I added the following code into the Sub New section of my application: –
    If My.Settings.ShouldUpgrade Then
    Dim instance As ApplicationSettingsBase
    instance = My.Settings
    instance.Upgrade()
    My.Settings(“ShouldUpgrade”) = False
    My.Settings.Save()
    End If

    This probably would work if added to the “MySettingsLoaded()” section of the Settings code, instead of the application’s Sub New.

    You may find the following pages useful too:
    http://coding.infoconex.com/post/2009/01/c-and-vbnet-preserving-or-persisting-user-settings-userconfig-after-upgrades.aspx

    http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k%28SYSTEM.CONFIGURATION.APPLICATIONSETTINGSBASE.UPGRADE%29;k%28TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV3.5%22%29;k%28DevLang-VB%29&rd=true

    I’d also like to comment on the statement that Application settings are read-only; they are read-only if you use the format My.Settings.MyApplicationSetting, but if you use the format My.Settings(“MyApplicationSetting”) this is readable/writeable at run-time.

    I hope this helps.

    Paul

  12. Thank you very much for this post, there is a lot of mis-information on this topic but this post is the most simple and most effective.
    Luckily, I managed to key in the right keywords into Google to find this blog.
    i was using *.ini files for years, not anymore….

  13. Hi,

    I am developing the web application in vb.net. Actullay i have a problem with lables highlighitng. In my application i have one option for user to highlight the specific label after clicking that ” Enable highlighting ” option. My qns is if user has selected one field as highlighted ,once the user logged off and loggig into that application, still user see that the label should be highlighted. How can we start to write the code for this ?

  14. Great post. I have a question about user settings:
    If we have multiple .settings files related to different groups of settings, is it possible to iterate through all those settings in user.config file and access the settings and the group of each setting?
    I can iterate through Properties.Settings.Default.Properties and access the settings, but don’t know how to do the same thing with multiple .settings and groups.

  15. thomas mercer says:

    I wish I would have read this first. Nice info on the User Settings. My problem is that as long as the application is running, the user settings persist. But, after a few builds when developing (.net 2010 fw4) or the next day when I test the application the user settings do not load. The User.config file is there, the properties are there; the default properties in the App.config will get loaded. Will this happen when users install it, will they have to keep resetting the properties?

    • Be sure to sync configurations in Visual Studio, especially if you rebuilt with a new version number as they are version specific. Users will always load the correct config for their version…that is my understanding.

Trackbacks

  1. […] 298 Originally Posted by TripleD and today I wasn't happy with using stream reader/writers for my settings file, so I integrated it into the registry. I suggest staying away from the registry, but there's no reason to use stream reader/writers as the .NET framework has a very nice Settings feature built-in. Here's a short article about the Settings: Easily Save and Retrieve Application and User Settings in VB.NET or C# Apps | DonDraper.com […]

Speak Your Mind

*