Saving User Preferences and Settings in your C# Application

Methods for Saving User Preferences and Settings within your C# Application using the Registry, to a SQL Database or to an XML file.

By Tim Trott | C# ASP.Net MVC | May 15, 2011
1,291 words, estimated reading time 5 minutes.

Microsoft .Net provides a powerful method for storing and retrieving user settings - something almost every application will at some stage need to do. This article will show you how to quickly and easily save settings to the Registry, to a SQL Database or an XML file.

Saving and loading user settings was formerly done using the trusty old INI configuration file, and more recently using the system Registry. While these two methods are perfectly valid, a more structured and scalable method is to use the .Net provided tools.

The first thing you need is a class that holds all the data you need to save, in this example, we are creating a simple class called UserPreferences which contains two strings and an integer.

C#
public class UserPreferences
{
    internal string _DisplayName;
    public string DisplayName
    {
        get { return _DisplayName; }
        set { _DisplayName = value; }
    }

    internal string _Company;
    public string Company
    {
        get { return _Company; }
        set { _Company = value; }
    }

    internal int _SomeValue;
    public int SomeValue
    {
        get { return _SomeValue; }
        set { _SomeValue = value; }
    }
}

This class will form a basis for each of the derived classes that we will use for storing the information in XML, Registry and Database.

XML Serialization

We have already seen XML Serialization in a previous tutorial, so I will keep this section short.

The first thing to do is mark the class as Serializable by inserting the [Serializable] attribute before the declaration or create a class that implements the ISerializable interface.

To save the user preferences class to an XML file simply create an XML Writer and invoke the Serialize method.

C#
UserPreferences up = new UserPreferences();

XmlSerializer mySerializer = new XmlSerializer(typeof(UserPreferences));
StreamWriter myWriter = new StreamWriter("c:/prefs.xml");
mySerializer.Serialize(myWriter, up);
myWriter.Close();

To read the data back in, you simply call the Deserialize method.

C#
UserPreferences up;

XmlSerializer mySerializer = new XmlSerializer(typeof(UserPreferences));
FileStream myFileStream = new FileStream("c:/prefs.xml",FileMode.Open);

up = (myTestClass)mySerializer.Deserialize(myFileStream);

You could also implement the IFormatter interface which will allow you to format the data and save it within a SOAP XML package using SoapFormatter or using a BinaryFormatter to store the data in a binary format.

Saving Settings within a SQL Database

If you are developing an application that relies on data stored within a database (i.e. the program will not function without the database) then it makes sense to store configuration settings for the application within the database as well. This allows for a distributed model where the application can be downloaded to any client machine and settings retrieved from a central source.

We need to create an implementation of the class that will handle saving to the database. I am going to create a derived class which inherits the properties of UserPreferences as well as two new methods; one for saving to the database and one for loading the data back. Since we need to load the data each time the program is run (when we instantiate the UserPrefererences class) we can put the loading code into the constructor for the class.

You will need to add 'using System.Data.SqlClient;' to your references.

C#
public class SQLUserPreferences : UserPreferences
{
    public SQLUserPreferences()
    {
        string connectionString = "Data Source=.SQLEXPRESS;AttachDbFilename="C:DOCUMENTS AND SETTINGSTROTTTMY DOCUMENTSVISUAL STUDIO 2005PROJECTSWINDOWSAPPLICATION5WINDOWSAPPLICATION5DATABASE1.MDF";Integrated Security=True;Connect Timeout=30;User Instance=True";
        SqlConnection sqlCon = new SqlConnection(connectionString);

        sqlCon.Open();
        string commandString = "SELECT * FROM appSettings WHERE UserLogon = '" +
        System.Environment.UserDomainName + "" +
        System.Environment.UserName.ToString() + "'";

        SqlCommand sqlCmd = new SqlCommand(commandString, sqlCon);
        SqlDataReader dr = sqlCmd.ExecuteReader();

        while (dr.Read())
        {
            / Index 0 contains the domain/username used 
            / as a primary key for the database.
            _DisplayName = dr.GetString(1);
            _Company = dr.GetString(2);
            _SomeValue = dr.GetInt32(3);
        }

        dr.Close();
        sqlCon.Close();
    }

    public void Save()
    {
        string connectionString = "Data Source=localhost; Integrated Security=SSPI; Initial Catalog=appSettings";
        SqlConnection sqlCon = new SqlConnection(connectionString);

        sqlCon.Open();
        string commandString = "UPDATE appSettings SET " +
          "DisplayName = '" + _DisplayName + "', " +
          "Company = '" + _Company + "', " +
          "SomeValue = " + _SomeValue +
          " WHERE UserLogon = '" +
          System.Environment.UserDomainName + "/" +
          System.Environment.UserName + "'";

        SqlCommand sqlCmd = new SqlCommand(commandString, sqlCon);
        sqlCmd.ExecuteNonQuery();
        sqlCon.Close();
    }
}

Saving Settings to the Registry

The Windows registry is a general-purpose mechanism for storing information that is to be maintained when a Windows application terminates. The .Net framework provides a class that provides easy access to registry methods. The registry contains many locations, called keys, such as HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER. These are a few of the read-only base keys that contain information about users, the operating system, the software installed and the settings for the currently logged-on user.

We are going to create a similar derived class to the one we created for SQL Databases; in fact, the technique is the same. You will need to add a reference to the namespace Microsoft.Win32.

You will need to add 'using Microsoft.Win32;' to your references.

C#
public class RegUserPreferences : UserPreferences
{
    public RegUserPreferences()
    {
        RegistryKey UserPrefs = Registry.CurrentUser.OpenSubKey("SOFTWAREYour-Company-NameApp-Name", true);

        if (UserPrefs != null)
        {
            _DisplayName = UserPrefs.GetValue("DisplayName").ToString();
            _Company = UserPrefs.GetValue("Company").ToString();
            _SomeValue = int.Parse(UserPrefs.GetValue("SomeValue").ToString());
        }
        else
        {
            / Key did not exist so use defaults
            _DisplayName = System.Environment.UserName;
            _Company = System.Environment.UserDomainName;
            _SomeValue = 0;
        }
    }

    public void Save()
    {
        RegistryKey UserPrefs = Registry.CurrentUser.OpenSubKey("SOFTWAREYour-Company-NameApp-Name", true);

        if (UserPrefs == null)
        {
            / Value does not already exist so create it
            RegistryKey newKey = Registry.CurrentUser.OpenSubKey("SOFTWAREYour-Company-Name", true);
            UserPrefs = newKey.CreateSubKey("App-Name");
        }

        UserPrefs.SetValue("DisplayName", _DisplayName);
        UserPrefs.SetValue("Company", _Company);
        UserPrefs.SetValue("SomeValue", _SomeValue);
    }
}

Reading and Writing INI Files with C# - Old School Configs

A short snippet showing how to perform reading and writing from old school INI Files with C#. Back to basics way of saving user settings. This short snippet allows you to quickly read and write settings from an old school INI configuration file. Yes I still use INI files!

INI files are a configuration file used by Windows that consists of a text-based content with a structure and syntax comprising key-value pairs for properties, and sections that organize the properties. Before the Windows Registry came into being with Windows 95, even Windows used INI files to store all its configuration settings.

INI Files with C# are small, fast, portable and work. On the downsides, they do not natively support multi user settings or group policies so if you need multi-user support then you may wish to check the other methods linked at the bottom of this article.

The example INI file is from the system.ini from Windows 3.1. It defines a boot section, bood.description sub-section and a 386enh section. Within these sections there are key/value pairs for each setting.

[boot]
network.drv = isnet.drv

[boot.description]
network.drv = Invisible LAN (for Windows 3.0, 3.1, and 3.11)

[386enh]
network = *vnetbios, *dosnet
FileSysChange = off
InDOSPolling = TRUE
INT28Critical = TRUE
ReflectDosInt2A = FALSE
UniqueDOSPSP = FALSE
LPT1AutoAssign = 0
LPT2AutoAssign = 0
LPT3AutoAssign = 0
PerVMFILES = 0
TimerCriticalSection = 1000

Now we know what INI files are all about, lets take a look at Reading and Writing INI Files with C#.

C#
using System;
using System.Runtime.InteropServices;
using System.Text;

public static class IniFile
{
  [DllImport("kernel32")]
  private static extern long WritePrivateProfileString(string section,string key, string val, string filePath);
  [DllImport("kernel32")]
  private static extern int GetPrivateProfileString(string section,string key, string def, StringBuilder retVal,int size, string filePath);

  public static void WriteValue(string path, string Section, string Key, string Value)
  {
    WritePrivateProfileString(Section, Key, Value, path);
  }

  public static string ReadValue(string path, string Section, string Key)
  {
    StringBuilder temp = new StringBuilder(255);
    int i = GetPrivateProfileString(Section, Key, "", temp, 255, path);
    return temp.ToString();
  }
}

Usage is very simple, simply call IniFile.WriteValue or IniFile.ReadValue with the full path to the INI file, the section name and the configuration key to write and read INI Files with C#.

This is a back to basics way of saving user settings in a text file. See the article below for other ways, including Windows Registry, Config XML files and more.

Was this article helpful to you?
 

Related ArticlesThese articles may also be of interest to you

CommentsShare your thoughts in the comments below

If you enjoyed reading this article, or it helped you in some way, all I ask in return is you leave a comment below or share this page with your friends. Thank you.

This post has 2 comment(s). Why not join the discussion!

We respect your privacy, and will not make your email public. Learn how your comment data is processed.

  1. RY

    On Monday 11th of January 2021, ryan said

    mono doesnt like [DllImport("kernel32")]
    This solution causes issues when trying to run .net code under mono on linux

  2. AA

    On Monday 1st of December 2014, Ahmad Ali said

    You saved a lot of time and stress. I was in a hurry and could not find any solution. Built-in settings were not being persistent even after all tries and save() etc. Registery was not a go because Click Once dont support admin rights and hence I can not publish my app.

    You are awesome.