Question

Ce que je veux réaliser est très simple: je dispose d’une application Windows Forms (.NET 3.5) qui utilise un chemin pour la lecture des informations. Ce chemin peut être modifié par l'utilisateur à l'aide du formulaire d'options fourni.

Maintenant, je veux enregistrer la valeur du chemin dans un fichier pour une utilisation ultérieure. Ce serait l'un des nombreux paramètres enregistrés dans ce fichier. Ce fichier serait placé directement dans le dossier de l'application.

Je comprends que trois options sont disponibles:

  • Fichier ConfigurationSettings (appname.exe.config)
  • Registre
  • Fichier XML personnalisé

J'ai lu que le fichier de configuration .NET n'est pas prévu pour y sauvegarder les valeurs. En ce qui concerne le registre, je voudrais aller aussi loin que possible.

Cela signifie-t-il que je devrais utiliser un fichier XML personnalisé pour enregistrer les paramètres de configuration? Si tel est le cas, j'aimerais voir un exemple de code (C #).

J'ai assisté à d'autres discussions sur ce sujet, mais ce n'est toujours pas clair pour moi.

Était-ce utile?

La solution

Si vous travaillez avec Visual Studio, il est assez facile d’obtenir des paramètres persistants. Cliquez avec le bouton droit sur le projet dans l'Explorateur de solutions, choisissez Propriétés. Sélectionnez l'onglet Paramètres, cliquez sur l'hyperlien si les paramètres n'existent pas. Utilisez l'onglet Paramètres pour créer les paramètres de l'application. Visual Studio crée les fichiers Settings.settings et Settings.Designer.settings qui contiennent la classe singleton Settings héritée de ApplicationSettingsBase . Vous pouvez accéder à cette classe à partir de votre code pour lire / écrire les paramètres de l'application:

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

Cette technique est applicable à la fois à la console, à Windows Forms et aux autres types de projets.

Notez que vous devez définir la propriété scope de vos paramètres. Si vous sélectionnez Domaine d'application, cliquez ensuite sur Paramètres.Défaut. & Lt; votre propriété > sera en lecture seule.

Autres conseils

Si vous envisagez de sauvegarder dans un fichier du même répertoire que votre exécutable, voici une solution intéressante utilisant Format JSON :

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;
        }
    }
}

Le registre est interdit. Vous ne savez pas si l'utilisateur qui utilise votre application dispose des droits suffisants pour écrire dans le registre.

Vous pouvez utiliser le fichier app.config pour enregistrer les paramètres au niveau de l'application (identiques pour chaque utilisateur qui utilise votre application).

Je stockais les paramètres spécifiques à l'utilisateur dans un fichier XML, qui serait enregistré dans Stockage isolé ou dans le Répertoire SpecialFolder.ApplicationData .

De plus, à partir de .NET 2.0, il est possible de stocker les valeurs dans le fichier <=>.

La classe ApplicationSettings ne prend pas en charge l'enregistrement des paramètres dans le fichier app.config. En effet, les applications fonctionnant avec un compte utilisateur correctement sécurisé (pensez à Vista UAC) n’ont pas d’accès en écriture au dossier d’installation du programme.

Vous pouvez combattre le système avec la classe ConfigurationManager. Mais la solution de contournement la plus simple est d'aller dans le concepteur de paramètres et de changer la portée du paramètre en utilisateur. Si cela cause des difficultés (par exemple, le paramètre est pertinent pour chaque utilisateur), vous devez placer votre fonction Options dans un programme séparé pour pouvoir demander l'invite d'élévation de privilèges. Ou renoncez à l'aide d'un paramètre.

L'argument registry / configurationSettings / XML semble toujours très actif. Je les ai tous utilisés au fur et à mesure de l'évolution de la technologie, mais mon préféré est basé sur Le système de Threed associé à Stockage isolé .

L'exemple suivant permet de stocker des objets nommés propriétés dans un fichier de stockage isolé. Tels que:

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

Les propriétés peuvent être récupérées en utilisant:

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

Il ne s'agit que d'un échantillon, qui ne suggère pas les meilleures pratiques.

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) { }
        }
    }
}

Je voulais partager une bibliothèque que j'ai construite pour cela. C'est une petite bibliothèque, mais une grosse amélioration (IMHO) par rapport aux fichiers .settings.

La bibliothèque s'appelle Jot (GitHub) , voici un ancien L'article de projet de code que j'ai écrit à ce sujet.

Voici comment vous l'utiliseriez pour suivre la taille et l'emplacement d'une fenêtre:

public MainWindow()
{
    InitializeComponent();

    _stateTracker.Configure(this)
        .IdentifyAs("MyMainWindow")
        .AddProperties(nameof(Height), nameof(Width), nameof(Left), nameof(Top), nameof(WindowState))
        .RegisterPersistTrigger(nameof(Closed))
        .Apply();
}

Avantages par rapport aux fichiers .settings: le code est considérablement réduit et il est beaucoup moins sujet aux erreurs car il suffit de mentionner chaque propriété une fois .

Avec les fichiers de paramètres, vous devez mentionner chaque propriété cinq : une fois lorsque vous créez explicitement la propriété et quatre autres fois dans le code qui copie les valeurs dans les deux sens.

Le stockage, la sérialisation, etc. sont entièrement configurables. Lorsque les objets cibles sont créés par un conteneur IOC, vous pouvez [le lier] [] pour qu'il applique automatiquement le suivi à tous les objets qu'il résout de sorte que tout ce que vous avez à faire pour rendre une propriété persistante soit de slap un attribut [Trackable]. dessus.

C'est hautement configurable, vous pouvez configurer: - lorsque les données sont persistées et appliquées globalement ou pour chaque objet suivi - comment il est sérialisé - où il est stocké (fichier, base de données, en ligne, stockage isolé, registre, par exemple) - règles pouvant annuler l'application / la persistance de données pour une propriété

Croyez-moi, la bibliothèque est excellente!

Un moyen simple consiste à utiliser un objet de données de configuration, à l'enregistrer en tant que fichier XML avec le nom de l'application dans le dossier local et à le relire au démarrage.

Voici un exemple pour stocker la position et la taille d'un formulaire.

La configuration dataobject est fortement typée et facile à utiliser:

[Serializable()]
public class CConfigDO
{
    private System.Drawing.Point m_oStartPos;
    private System.Drawing.Size m_oStartSize;

    public System.Drawing.Point StartPos
    {
        get { return m_oStartPos; }
        set { m_oStartPos = value; }
    }

    public System.Drawing.Size StartSize
    {
        get { return m_oStartSize; }
        set { m_oStartSize = value; }
    }
}

Une classe de gestionnaire pour la sauvegarde et le chargement:

public class CConfigMng
{
    private string m_sConfigFileName = System.IO.Path.GetFileNameWithoutExtension(System.Windows.Forms.Application.ExecutablePath) + ".xml";
    private CConfigDO m_oConfig = new CConfigDO();

    public CConfigDO Config
    {
        get { return m_oConfig; }
        set { m_oConfig = value; }
    }

    // Load configuration file
    public void LoadConfig()
    {
        if (System.IO.File.Exists(m_sConfigFileName))
        {
            System.IO.StreamReader srReader = System.IO.File.OpenText(m_sConfigFileName);
            Type tType = m_oConfig.GetType();
            System.Xml.Serialization.XmlSerializer xsSerializer = new System.Xml.Serialization.XmlSerializer(tType);
            object oData = xsSerializer.Deserialize(srReader);
            m_oConfig = (CConfigDO)oData;
            srReader.Close();
        }
    }

    // Save configuration file
    public void SaveConfig()
    {
        System.IO.StreamWriter swWriter = System.IO.File.CreateText(m_sConfigFileName);
        Type tType = m_oConfig.GetType();
        if (tType.IsSerializable)
        {
            System.Xml.Serialization.XmlSerializer xsSerializer = new System.Xml.Serialization.XmlSerializer(tType);
            xsSerializer.Serialize(swWriter, m_oConfig);
            swWriter.Close();
        }
    }
}

Vous pouvez maintenant créer une instance et utiliser les événements de chargement et de fermeture de votre formulaire:

    private CConfigMng oConfigMng = new CConfigMng();

    private void Form1_Load(object sender, EventArgs e)
    {
        // Load configuration
        oConfigMng.LoadConfig();
        if (oConfigMng.Config.StartPos.X != 0 || oConfigMng.Config.StartPos.Y != 0)
        {
            Location = oConfigMng.Config.StartPos;
            Size = oConfigMng.Config.StartSize;
        }
    }

    private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    {
        // Save configuration
        oConfigMng.Config.StartPos = Location;
        oConfigMng.Config.StartSize = Size;
        oConfigMng.SaveConfig();
    }

Et le fichier XML produit est également lisible:

<?xml version="1.0" encoding="utf-8"?>
<CConfigDO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <StartPos>
    <X>70</X>
    <Y>278</Y>
  </StartPos>
  <StartSize>
    <Width>253</Width>
    <Height>229</Height>
  </StartSize>
</CConfigDO>

Je n'aime pas la solution proposée consistant à utiliser web.config ou app.config. Essayez de lire votre propre XML. Consultez Fichiers de paramètres XML & # 8211; Plus de web.config .

Autres options, au lieu d'utiliser un fichier XML personnalisé, nous pouvons utiliser un format de fichier plus convivial: fichier JSON ou YAML.

  • Si vous utilisez .NET 4.0 dynamic, cette bibliothèque est vraiment facile à utiliser (sérialiser, désérialiser, support des objets imbriqués et ordonner la sortie si vous le souhaitez + en fusionnant plusieurs paramètres) JsonConfig (l'utilisation est équivalente à ApplicationSettingsBase)
  • Pour la bibliothèque de configuration .NET YAML ... Je n'en ai pas trouvé facile à utiliser comme JsonConfig

Vous pouvez stocker votre fichier de paramètres dans plusieurs dossiers spéciaux (pour tous les utilisateurs et par utilisateur), comme indiqué ici Énumération Environment.SpecialFolder et plusieurs fichiers (lecture par défaut uniquement, par rôle, par utilisateur, etc.)

Si vous choisissez d'utiliser plusieurs paramètres, vous pouvez les fusionner: Par exemple, fusionner les paramètres pour les paramètres par défaut + BasicUser + AdminUser. Vous pouvez utiliser vos propres règles: la dernière remplace la valeur, etc.

& "Cela signifie-t-il que je devrais utiliser un fichier XML personnalisé pour enregistrer les paramètres de configuration? &"; Non pas forcément. Nous utilisons SharpConfig pour de telles opérations.

Par exemple, si le fichier de configuration est comme ça

[General]
# a comment
SomeString = Hello World!
SomeInteger = 10 # an inline comment

Nous pouvons récupérer des valeurs comme celle-ci

var config = Configuration.LoadFromFile("sample.cfg");
var section = config["General"];

string someString = section["SomeString"].StringValue;
int someInteger = section["SomeInteger"].IntValue;

Il est compatible avec .Net 2.0 et supérieur. Nous pouvons créer des fichiers de configuration à la volée et les sauvegarder ultérieurement. Source: http://sharpconfig.net/ Github: https://github.com/cemdervis/SharpConfig

J'espère que cela vous aidera.

Autant que je sache, .NET prend en charge les paramètres persistants à l'aide de la fonction intégrée de paramètres d'application:

  

La fonctionnalité Paramètres d'application de Windows Forms facilite la création, le stockage et la gestion des préférences personnalisées pour les applications et les utilisateurs sur l'ordinateur client. Avec les paramètres d'application Windows Forms, vous pouvez stocker non seulement des données d'application telles que les chaînes de connexion à la base de données, mais également des données spécifiques à l'utilisateur, telles que les préférences d'application utilisateur. À l'aide de Visual Studio ou d'un code géré personnalisé, vous pouvez créer de nouveaux paramètres, les lire depuis et les écrire sur le disque, les lier aux propriétés de vos formulaires et valider les données de paramètres avant le chargement et l'enregistrement.    - http://msdn.microsoft.com/en-us/library/k4s6c3a0 .aspx

Parfois, vous souhaitez vous débarrasser de ces paramètres conservés dans le fichier web.config ou app.config traditionnel. Vous souhaitez un contrôle plus fin sur le déploiement de vos entrées de paramètres et la conception de données séparées. Ou bien, il faut activer l'ajout de nouvelles entrées au moment de l'exécution.

Je peux imaginer deux bonnes options:

  • La version fortement typée et
  • La version orientée objet.

L’avantage de la version fortement typée réside dans les noms et les valeurs des paramètres fortement typés. Il n'y a aucun risque de mélanger des noms ou des types de données. L'inconvénient est que plus de paramètres doivent être codés et ne peuvent pas être ajoutés au moment de l'exécution.

Avec la version orientée objet, l’avantage est que de nouveaux paramètres peuvent être ajoutés au moment de l’exécution. Mais vous n'avez pas de noms et de valeurs fortement typés. Doit être prudent avec les identificateurs de chaîne. Doit connaître le type de données enregistré précédemment lors de l'obtention d'une valeur.

Vous pouvez trouver le code des deux implémentations entièrement fonctionnelles ICI .

public static class SettingsExtensions
{
    public static bool TryGetValue<T>(this Settings settings, string key, out T value)
    {
        if (settings.Properties[key] != null)
        {
            value = (T) settings[key];
            return true;
        }

        value = default(T);
        return false;
    }

    public static bool ContainsKey(this Settings settings, string key)
    {
        return settings.Properties[key] != null;
    }

    public static void SetValue<T>(this Settings settings, string key, T value)
    {
        if (settings.Properties[key] == null)
        {
            var p = new SettingsProperty(key)
            {
                PropertyType = typeof(T),
                Provider = settings.Providers["LocalFileSettingsProvider"],
                SerializeAs = SettingsSerializeAs.Xml
            };
            p.Attributes.Add(typeof(UserScopedSettingAttribute), new UserScopedSettingAttribute());
            var v = new SettingsPropertyValue(p);
            settings.Properties.Add(p);
            settings.Reload();
        }
        settings[key] = value;
        settings.Save();
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top