Coder Perfect

In a Windows Forms application, how can I store application settings?

Problem

The goal I’m aiming for is straightforward: I’ve got a Windows Forms (.NET 3.5) application that reads data from a route. The user can change this path by filling out the alternatives form I give.

Now I’d like to store the path value to a file so that I may use it later. One of the numerous parameters saved to this file would be this. This file would sit directly in the application folder.

I understand three options are available:

I read that the .NET configuration file is not foreseen for saving values back to it. As for the registry, I would like to get as far away from it as possible.

Does this imply that I should save configuration settings in a bespoke XML file?

If that’s the case, I’d like to see a C# code example.

I’ve read previous talks on this topic, but I’m still not sure what to make of it.

Asked by Fueled

Solution #1

It’s rather simple to get persistent settings if you work with Visual Studio. In Solution Explorer, right-click on the project and select Properties. If the Settings tab does not exist, choose it and click the links.

Create application settings using the Settings tab. Visual Studio creates the files Settings.settings and Settings.Designer.settings that contain the singleton class Settings inherited from ApplicationSettingsBase. You can access this class from your code to read/write application settings:

Properties.Settings.Default["SomeProperty"] = "Some Value";
Properties.Settings.Default.Save(); // Saves settings in application configuration file

This method works for console, Windows Forms, and other types of projects.

It’s worth noting that the scope attribute of your settings must be set. Settings.Default.your property> will be read-only if you choose Application scope.

Microsoft Docs – How To: Write User Settings at Run Time using C#

Answered by aku

Solution #2

If you want to save to a file in the same directory as your executable, here’s a good way to do it with the JSON format:

using System;
using System.IO;
using System.Web.Script.Serialization;

namespace MiscConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            MySettings settings = MySettings.Load();
            Console.WriteLine("Current value of 'myInteger': " + settings.myInteger);
            Console.WriteLine("Incrementing 'myInteger'...");
            settings.myInteger++;
            Console.WriteLine("Saving settings...");
            settings.Save();
            Console.WriteLine("Done.");
            Console.ReadKey();
        }

        class MySettings : AppSettings<MySettings>
        {
            public string myString = "Hello World";
            public int myInteger = 1;
        }
    }

    public class AppSettings<T> where T : new()
    {
        private const string DEFAULT_FILENAME = "settings.json";

        public void Save(string fileName = DEFAULT_FILENAME)
        {
            File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(this));
        }

        public static void Save(T pSettings, string fileName = DEFAULT_FILENAME)
        {
            File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(pSettings));
        }

        public static T Load(string fileName = DEFAULT_FILENAME)
        {
            T t = new T();
            if(File.Exists(fileName))
                t = (new JavaScriptSerializer()).Deserialize<T>(File.ReadAllText(fileName));
            return t;
        }
    }
}

Answered by Trevor

Solution #3

The registry is off the table. You’re not sure if the user who uses your app has the necessary permissions to write to the registry.

You can save application-level settings in the app.config file (that are the same for each user who uses your application).

User-specific preferences would be kept in an XML file in Isolated Storage or in the SpecialFolder.ApplicationData directory.

Furthermore, starting with.NET 2.0, it is able to save values to the app.config file.

Answered by Frederik Gheysels

Solution #4

Saving settings to the app.config file is not supported by the ApplicationSettings class. This is by design; applications running under a properly secured user account (think Vista UAC) don’t have write access to the program’s installation folder.

The ConfigurationManager class can be used to combat the system. However, a simple fix is to alter the setting’s scope to User in the Settings designer. If this is inconvenient (for example, if the setting affects all users), you should put your Options feature in a separate program so you may request the privilege elevation prompt. Alternatively, don’t use a setting at all.

Answered by Hans Passant

Solution #5

The registry/configurationSettings/XML argument appears to be extremely active right now. As technology has advanced, I’ve used them all, but my favorite is based on Threed’s approach paired with Isolated Storage.

The sample below demonstrates how to save an object’s named properties to a file in isolated storage. For example:

AppSettings.Save(myobject, "Prop1,Prop2", "myFile.jsn");

The following methods can be used to recover properties:

AppSettings.Load(myobject, "myFile.jsn");

It is only a sample and does not represent best practices.

internal static class AppSettings
{
    internal static void Save(object src, string targ, string fileName)
    {
        Dictionary<string, object> items = new Dictionary<string, object>();
        Type type = src.GetType();

        string[] paramList = targ.Split(new char[] { ',' });
        foreach (string paramName in paramList)
            items.Add(paramName, type.GetProperty(paramName.Trim()).GetValue(src, null));

        try
        {
            // GetUserStoreForApplication doesn't work - can't identify.
            // application unless published by ClickOnce or Silverlight
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForAssembly();
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.Create, storage))
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.Write((new JavaScriptSerializer()).Serialize(items));
            }

        }
        catch (Exception) { }   // If fails - just don't use preferences
    }

    internal static void Load(object tar, string fileName)
    {
        Dictionary<string, object> items = new Dictionary<string, object>();
        Type type = tar.GetType();

        try
        {
            // GetUserStoreForApplication doesn't work - can't identify
            // application unless published by ClickOnce or Silverlight
            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForAssembly();
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.Open, storage))
            using (StreamReader reader = new StreamReader(stream))
            {
                items = (new JavaScriptSerializer()).Deserialize<Dictionary<string, object>>(reader.ReadToEnd());
            }
        }
        catch (Exception) { return; }   // If fails - just don't use preferences.

        foreach (KeyValuePair<string, object> obj in items)
        {
            try
            {
                tar.GetType().GetProperty(obj.Key).SetValue(tar, obj.Value, null);
            }
            catch (Exception) { }
        }
    }
}

Answered by Boczek

Post is based on https://stackoverflow.com/questions/453161/how-can-i-save-application-settings-in-a-windows-forms-application