Il est recommandé d’enregistrer les parameters de l’application dans une application Windows Forms

Ce que je veux réaliser est très simple: j’ai une application Windows Forms (.NET 3.5) qui utilise un chemin pour lire les informations. Ce chemin peut être modifié par l’utilisateur en utilisant les options que je fournis.

Maintenant, je veux enregistrer la valeur du chemin dans un fichier pour une utilisation ultérieure. Ce serait l’un des nombreux parameters 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)
  • Enregistrement
  • Fichier XML personnalisé

J’ai lu que le fichier de configuration .NET n’est pas prévu pour y enregistrer des valeurs. En ce qui concerne le registre, je voudrais m’en éloigner le plus possible.

Est-ce que cela signifie que je devrais utiliser un fichier XML personnalisé pour enregistrer les parameters de configuration? Si oui, j’aimerais voir un exemple de code de cela (C #).

J’ai vu d’autres discussions sur ce sujet, mais ce n’est pas encore clair pour moi.

Si vous travaillez avec Visual Studio, il est assez facile d’obtenir des parameters 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 parameters n’existent pas. Utilisez l’onglet Paramètres pour créer des parameters d’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 des parameters d’application:

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

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

Notez que vous devez définir la propriété scope de vos parameters. Si vous sélectionnez la scope de l’application, alors Settings.Default. sera en lecture seule.

Si vous envisagez d’enregistrer dans un fichier dans le même répertoire que votre exécutable, voici une solution intéressante qui utilise le format JSON :

 using System; using System.IO; using System.Web.Script.Serialization; namespace MiscConsole { class Program { static void Main(ssortingng[] 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 { public ssortingng mySsortingng = "Hello World"; public int myInteger = 1; } } public class AppSettings where T : new() { private const ssortingng DEFAULT_FILENAME = "settings.json"; public void Save(ssortingng fileName = DEFAULT_FILENAME) { File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(this)); } public static void Save(T pSettings, ssortingng fileName = DEFAULT_FILENAME) { File.WriteAllText(fileName, (new JavaScriptSerializer()).Serialize(pSettings)); } public static T Load(ssortingng fileName = DEFAULT_FILENAME) { T t = new T(); if(File.Exists(fileName)) t = (new JavaScriptSerializer()).Deserialize(File.ReadAllText(fileName)); return t; } } } 

Le registre est un no-go. Vous n’êtes pas sûr que 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 parameters au niveau de l’application (identiques pour chaque utilisateur de votre application).

Je stocker les parameters spécifiques à l’utilisateur dans un fichier XML, qui serait enregistré dans le stockage isolé ou dans le répertoire SpecialFolder.ApplicationData .

À côté de cela, à partir de .NET 2.0, il est possible de stocker des valeurs dans le fichier app.config .

La classe ApplicationSettings ne prend pas en charge l’enregistrement des parameters dans le fichier app.config. C’est tout à fait par conception, les applications qui fonctionnent avec un compte d’utilisateur correctement sécurisé (pensez à Vista UAC) n’ont pas access en écriture au dossier d’installation du programme.

Vous pouvez combattre le système avec la classe ConfigurationManager . Mais la solution sortingviale consiste à aller dans le concepteur de parameters et à changer l’étendue du paramètre en utilisateur. Si cela provoque des difficultés (par exemple, le paramètre est pertinent pour chaque utilisateur), vous devez placer votre fonctionnalité Options dans un programme distinct pour pouvoir demander l’invite d’élévation de privilèges. Ou renoncez à utiliser un paramètre.

Je voulais partager une bibliothèque que j’ai construite pour cela. C’est une petite bibliothèque, mais une grande amélioration (IMHO) sur les fichiers .settings.

La bibliothèque s’appelle Jot (GitHub) , voici un ancien article de The Code Project que j’ai écrit à ce sujet.

Voici comment l’utiliser 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(); } 

L’avantage par rapport aux fichiers .settings: il y a beaucoup moins de code, et il est beaucoup moins sujet aux erreurs puisque vous ne devez mentionner qu’une seule fois chaque propriété.

Avec un fichier de parameters, vous devez mentionner chaque propriété cinq fois: une fois lorsque vous créez explicitement la propriété et quatre fois dans le code qui copie les valeurs dans les deux sens.

Le stockage, la sérialisation, etc. sont entièrement configurables. Lorsque vous utilisez l’ inversion du contrôle , vous pouvez le connecter de manière à ce qu’il applique automatiquement un suivi à tous les objects résolus, de sorte que tout ce que vous devez faire pour persister dans une propriété est de lui atsortingbuer un atsortingbut [Suivi].

J’écris tout cela, car je pense que la bibliothèque est de qualité supérieure et j’aimerais la vulgariser 🙂

L’argument registry / configurationSettings / XML semble toujours très actif. Je les ai tous utilisés, car la technologie a progressé, mais mon préféré est basé sur le système de Threed associé au stockage isolé .

L’exemple suivant permet de stocker des objects nommés propriétés dans un fichier dans un stockage isolé. Tel 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, ssortingng targ, ssortingng fileName) { Dictionary items = new Dictionary(); Type type = src.GetType(); ssortingng[] paramList = targ.Split(new char[] { ',' }); foreach (ssortingng 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, ssortingng fileName) { Dictionary items = new Dictionary(); 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>(reader.ReadToEnd()); } } catch (Exception) { return; } // If fails - just don't use preferences. foreach (KeyValuePair obj in items) { try { tar.GetType().GetProperty(obj.Key).SetValue(tar, obj.Value, null); } catch (Exception) { } } } } 

Une méthode simple consiste à utiliser un object 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.

L’object de configuration est fortement typé 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 l’enregistrement et le chargement:

 public class CConfigMng { private ssortingng 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(); } } } 

Maintenant, vous pouvez créer une instance et l’utiliser dans 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:

    70 278   253 229   

Je n’aime pas la solution proposée pour l’utilisation de web.config ou app.config . Essayez de lire votre propre XML. Jetez un coup d’oeil aux fichiers de parameters XML – Plus besoin de web.config .

Pour autant que je sache, .NET prend en charge les parameters persistants à l’aide de la fonctionnalité de parameters d’application intégrée:

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

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 très simple à utiliser (sérialisation, désérialisation, prise en charge des objects nesteds et classement des résultats à votre convenance + fusion de plusieurs parameters en un seul) JsonConfig (l’utilisation est équivalente à ApplicationSettingsBase)
  • Pour la bibliothèque de configuration .NET YAML … Je n’en ai pas trouvé aussi facile à utiliser que JsonConfig

Vous pouvez stocker votre fichier de parameters dans plusieurs dossiers spéciaux (pour tous les utilisateurs et par utilisateur), comme indiqué ici Environment.SpecialFolder Enumeration et plusieurs fichiers (lecture seule par défaut, par rôle, par utilisateur, etc.)

  • Exemple pour obtenir le chemin du dossier spécial: C # obtenir le chemin de% AppData%

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

Parfois, vous voulez vous débarrasser de ces parameters conservés dans le fichier web.config ou app.config traditionnel. Vous souhaitez un contrôle plus précis du déploiement de vos entrées de parameters et de la conception séparée des données. Ou l’exigence est de permettre l’ajout de nouvelles entrées à l’exécution.

Je peux imaginer deux bonnes options:

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

L’avantage de la version fortement typée est le nom et les valeurs des parameters fortement typés. Il n’y a aucun risque de mélange de noms ou de types de données. L’inconvénient est que plus de parameters doivent être codés, ne peuvent pas être ajoutés à l’exécution.

Avec la version orientée object, l’avantage est que de nouveaux parameters peuvent être ajoutés à 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 .

“Cela signifie-t-il que je devrais utiliser un fichier XML personnalisé pour enregistrer les parameters 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 SomeSsortingng = 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"]; ssortingng someSsortingng = section["SomeSsortingng"].SsortingngValue; 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 nous pouvons les enregistrer plus tard. Source: http://sharpconfig.net/ Github: https://github.com/cemdervis/SharpConfig

J’espère que ça aide.

 public static class SettingsExtensions { public static bool TryGetValue(this Settings settings, ssortingng 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, ssortingng key) { return settings.Properties[key] != null; } public static void SetValue(this Settings settings, ssortingng key, T value) { if (settings.Properties[key] == null) { var p = new SettingsProperty(key) { PropertyType = typeof(T), Provider = settings.Providers["LocalFileSettingsProvider"], SerializeAs = SettingsSerializeAs.Xml }; p.Atsortingbutes.Add(typeof(UserScopedSettingAtsortingbute), new UserScopedSettingAtsortingbute()); var v = new SettingsPropertyValue(p); settings.Properties.Add(p); settings.Reload(); } settings[key] = value; settings.Save(); } }