Laden...

[Tutorial] Konfigurationsmodell im .NET Framework

Erstellt von Noodles vor 18 Jahren Letzter Beitrag vor 12 Jahren 138.087 Views
N
Noodles Themenstarter:in
4.644 Beiträge seit 2004
vor 18 Jahren
[Tutorial] Konfigurationsmodell im .NET Framework

Das neue Konfigurationsmodell im .NET Framework 2.0

Im .NET Framwork 1.1 können Konfigurationsdaten in der app.config gespeichert, aber nicht zur Laufzet geschrieben werden. Die Daten können über die Klasse ConfigurationSettings und deren Eigenschaft AppSettings abgerufen werden. Dies geschah über einen Indexer, was unter anderem den Nachteil hat, dass Laufzeitfehler durch Rechtschreibfehler entstehen konnten.
Weiterhin konnte man Daten nur lesen und nicht speichern.
Damit ist jetzt Schluß!
Im .NET Framework 2.0 können nun Anwendungsdaten und Benutzerdaten in einer Konfigurationsdatei gespeichert und Benutzerdaten auch geschrieben werden. Man sieht dies in dem folgenden Beispiel, einer Windows Forms Anwendung ( der Code befindet sich am Ende des Artikels ). Als erstes werden in den Projekteigenschaften, auf der Seite Settings, die Konfigurationsdaten angelegt.


Volle Bildgröße

In diesem Beispiel ist es ein Connectionstring mit dem Scope Application und eine Color Eigenschaft mit dem Scope User. Die Scopes kennzeichnen Anwendungs- und Benutzerdaten.
In der app.config sieht man nun unter applicationSettings bzw. userSettings die Daten.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, [...]" >
            <section name="MyCsharpConfigurationSample.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, [...]" />
        </sectionGroup>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, [...]" >
            <section name="MyCsharpConfigurationSample.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, [...]" />
        </sectionGroup>
    </configSections>
    <userSettings>
        <MyCsharpConfigurationSample.Properties.Settings>
            <setting name="MyBackColor" serializeAs="String">
                <value>255; 255; 128</value>
            </setting>
        </MyCsharpConfigurationSample.Properties.Settings>
    </userSettings>
    <applicationSettings>
        <MyCsharpConfigurationSample.Properties.Settings>
            <setting name="NothwindConnectionString" serializeAs="String">
                <value>Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI</value>
            </setting>
        </MyCsharpConfigurationSample.Properties.Settings>
    </applicationSettings>
</configuration>

Da in die app.config nicht geschrieben werden kann gibt es eine weitere Konfigurationsdatei, die user.config. Diese Datei findet man unter ( der Pfad ist für dieses Beispiel, daher kann es ab Anwendungsdaten abweichen )
C:\Dokumente und Einstellungen\UserName\Lokale Einstellungen\Anwendungsdaten\MyCsharpConfigurationSam\MyCsharpConfigurationSamp_Url_heky24hmkwdp50ge24kv42daxdajmqcc\1.0.0.0
In dieser Datei werden nun die Daten gespeichert, die veränderbar sind, sich also im Scope User befinden.
Die Datei wird erst geschrieben, sobald die erste Eigenschaft gespeichert wird, werden die Daten nur gelesen, wird auch keine user.config geschrieben.
Das Visual Studio generiert nun die Klasse Settings ( ProjectNameSpace.Properties ), in dieser Klasse findet man die typisierten Eigenschaften.
Jetzt erstellen wir das Beispiel und sehen die, in den Settings angegeben Farbe als Hintergrundfarbe der Form und den Connectionstring als Titel ( ist etwas realitiätsfremd, aber es soll ja auch nur als Beispiel dienen. ).
In dem Click Ereignis des Buttons öffnet sich ein Colordialog.

Wird dieser mit Ok bestätigt, wird die ausgewählte Farbe in der user.config. gespeichtert.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <userSettings>
        <MyCsharpConfigurationSample.Properties.Settings>
            <setting name="MyBackColor" serializeAs="String">
                <value>255; 128; 255</value>
            </setting>
        </MyCsharpConfigurationSample.Properties.Settings>
    </userSettings>
</configuration>

Anschließend laden wir Daten erneut ( Funktion: LoadConfigSettings() ), damit wir die Änderung sofort sehen.

Wenn man jetzt in der AssemblyInfo.cs die Versionsnummer der Assemblies verändert und das Beispiel erneut ausführt, sieht man, dass für die neue Version eine neue user.config Datei angelegt wird.

Der Code:

namespace MyCsharpConfigurationSample
{
    public partial class Form1 : Form
    {
        MyCSharpConfigurationSample.Properties.Settings mySettings = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.LoadConfigSettings();
        }

        private void LoadConfigSettings()
        {
            mySettings = new MyCSharpConfigurationSample.Properties.Settings();
            this.BackColor = mySettings.MyBackColor;
            this.Text = mySettings.NothwindConnectionString;
        }

        private void save_Click(object sender, EventArgs e)
        {
            if( colorDialog.ShowDialog() == DialogResult.OK )
            {
                mySettings.MyBackColor = colorDialog.Color;
                mySettings.Save();
                this.LoadConfigSettings();
            }
        }
    }
}
P
120 Beiträge seit 2005
vor 18 Jahren

Vielen Dank für Deinen Artikel, hat mir die Zeit verkürzt Zugang zu dieser Thematik zu finden.

Bei mir funktioniert das Beispiel auch, kann aber leider keine Konfigurationsdatei finden (user.config), in der die geänderten Daten geschrieben werden. Habe bei mir nur eine Datei TEST_SETTINGS.EXE-17368469.pf im Verzeichnis Windows\Prefetch gefunden, die aber den XML-Vorgaben nicht entspricht. Habe dazu die gesamte Festplatte nach Datum durchsucht. Seltsamerweise werden die Daten aber nach Neu-Start korrekt angezeigt.

Mir ist aufgefallen, das beim Start des Test_Settings\Test_Settings\obj\Debug\Test_Settings.exe Files andere Einstellungen gespeichert werden als wenn ich das Programm aus der Entwicklungsumgebung laufen lasse.

Gruß pegasus2

K
355 Beiträge seit 2004
vor 18 Jahren

Hmm mir is das ganze noch ein wenig suspekt und einfach zuwenig flexibel. Warum sieht MS nicht mal ein, dass man (ich) den Pfad und Namen der Config selber festlegen können sollte?

Was nützt mir ne App.Config in nem Pfad, der wie der oben?
Da installiert man 20x .NET 2.0 Programme und hat dann nach der Deinstallation nur noch Mull rumliegen. Warum nich die Config in denselben Ordner wie das Assembly?

Ne also da benutz ich doch lieber meine eigene Klasse, die die Einstellungen handelt. Is zwar auch nicht wirklich flexibel, aber da kann ich obige Punkte selbst bestimmen...genau dasselbe is nämlich mit dem AutoUpdate Teil. Viel zu unflexibel, da hab ich als Programmierer halt gerne die Kontrolle was passiert. Die Teile sind total undurchsichtig 🙁

N
Noodles Themenstarter:in
4.644 Beiträge seit 2004
vor 18 Jahren

Bei mir funktioniert das Beispiel auch, kann aber leider keine Konfigurationsdatei finden (user.config), in der die geänderten Daten geschrieben werden. Habe bei mir nur eine Datei TEST_SETTINGS.EXE-17368469.pf im Verzeichnis Windows\Prefetch gefunden, die aber den XML-Vorgaben nicht entspricht.

Was findest Du denn im Ordner:
C:\Dokumente und Einstellungen&lt;username>\Lokale Einstellungen\Anwendungsdaten

Mir ist aufgefallen, das beim Start des Test_Settings\Test_Settings\obj\Debug\Test_Settings.exe Files andere Einstellungen gespeichert werden als wenn ich das Programm aus der Entwicklungsumgebung laufen lasse.

Erkläre das mal bitte genauer?
Es wird immer die zuletzt gespeicherte Farbe angezeigt.
Hast Du vielleicht die Configuration auf Release und nicht auf Debug stehen?

M
456 Beiträge seit 2004
vor 18 Jahren

Was nützt mir ne App.Config in nem Pfad, der wie der oben?
Da installiert man 20x .NET 2.0 Programme und hat dann nach der Deinstallation nur noch Mull rumliegen. Warum nich die Config in denselben Ordner wie das Assembly?

Ganz einfach, weil das Verzeichnis, in dem eine Assembly installiert ist im Normalfall immer read only sein sollte. Schreibst du deine Configs ins Programmverzeichnis, dann läuft dein Prog nicht mehr mit eingeschränken Benutzerkonten. Das AppData Verzeichnis zu nutzen ist also durchaus sinnvoll.

Du glaubst nicht wie oft ich mich schon über schlecht programmierte Software aufgeregt habe, die ganau das macht und einfach nicht mit mehreren Benutzerkonten zurecht kommt. Es gibt leider immer noch Programmierer die meinen das alle Konfigurationen ins Programmverzeichnis gehören. Frei nach dem Motto: "It's not a bug it's a feature"

Und ja, du musst es nicht benutzen. Ich verwende auch mein eigenes Konfigurationssystem.

I am Jack's smirking revenge.
I am Jack's raging bile duct.
I am Jack's cold sweat.
I am Jack's complete lack of surprise.
I am Jack's broken heart.
I am Jack's wasted life.

P
120 Beiträge seit 2005
vor 18 Jahren

Erst mal vielen Dank für die Resonanz 🙂, habe wahrscheinlich bei der Suche das falsche Datum eingegeben, das hat man nun davon wenn man länger als 12 h am PC sitzt. Besitze insgesamt aber auch noch 8 andere Laufwerke, da kann man schon mal durcheinander kommen. Die Datei findet sich bei mir im Verzeichnis:
H:\Dokumente und Einstellungen\Peter\Lokale Einstellungen\Anwendungsdaten\org\Test_Settings.exe_Url_vjqladyrjy2zvqbvv4vupcc5evo5fue3\1.0.0.0

Na ja, vielleicht doch etwas zu gut versteckt. Jedenfalls hat das ganze dazu geführt, eine kleine Exkursion in XML zu starten. Da Registry-Einträge unter NET jetzt wieder im lokalen Verzeichnissen stehen sollten, keine schlechte Übung.

Hier noch ein bischen Code mit dem ich eine XML-Datei sowohl schreiben als auch lesen kann:


    private void Lese_XML_Konfiguration()
    {
      // Lese XML-Datei
      XmlDocument xmlDoc = new XmlDocument();
      XmlElement root;
      XmlNode node1,node2,node3;
      try
      {
        //Also hier bitte Vorsicht!! Probleme bei eingeschränkten Benutzerrechten!!
        xmlDoc.Load(Application.StartupPath + "\\Konfiguration.Xml");
        root = xmlDoc.DocumentElement;
        node1 = root;
      }
      catch
      {
        MessageBox.Show("Datei Konfiguration.xml nicht gefunden!");
        return;
      }
      string stnodeName = node1.Name;//Konfiguration
      if (node1.ChildNodes.Count > 0)
      {
        for (int K = 0; K < node1.ChildNodes.Count;K++)
        {
          node2 = node1.ChildNodes.Item(K);//Datenbank,Ansicht  
      
          if (node2.Name == "Datenbank")
          {
            if (node2.ChildNodes.Count > 0)
            {         
              for (int I = 0; I < node2.ChildNodes.Count; I++)
              {
                node3 = node2.ChildNodes.Item(I);//Alias,User,Password
                if (node3.Name == "Alias")
                {
                  tB_Alias.Text = node3.InnerText;
                }
                if (node3.Name == "User")
                {
                  tB_User.Text = node3.InnerText;
                }
                if (node3.Name == "Password")
                {
                  tB_Password.Text = node3.InnerText;
                }
              }
            }          
          }//Ende Datenbank

          if (node2.Name == "Ansicht")
          {
            if (node2.ChildNodes.Count > 0)
            {
              for (int I = 0; I < node2.ChildNodes.Count; I++)
              {
                node3 = node2.ChildNodes.Item(I);//Alias,User,Password
                if (node3.Name == "Color_Ruestzeit")
                {
                  tB_Ruestzeit.Text = node3.InnerText;
                }
                ...
                ...
            }
          }//Ende Ansicht
        }        
      }
    }

    //Einträge in XML-Dokument übernehmen
    private void btn_Uebernehmen_Click(object sender, EventArgs e)
    {
      //Also hier bitte Vorsicht!! Probleme bei eingeschränkten Benutzerrechten!!
      XmlTextWriter w = new XmlTextWriter(Application.StartupPath + "\\Konfiguration.Xml",Encoding.GetEncoding("ISO-8859-1"));
      try
      {
        w.WriteStartDocument();
        w.WriteComment("Konfigurationseinstellungen fuer Programm");
        w.WriteStartElement("Konfiguration");
        
        w.WriteStartElement("Datenbank");
        w.WriteStartElement("Alias");
        w.WriteString(tB_Alias.Text);
        w.WriteEndElement();
        w.WriteStartElement("User");
        w.WriteString(tB_User.Text);
        w.WriteEndElement();
        w.WriteStartElement("Password");
        w.WriteString(tB_Password.Text);        
        w.WriteEndElement();
        w.WriteEndElement();//Datenbank

        w.WriteStartElement("Ansicht");
        w.WriteStartElement("Color_Ruestzeit");
        w.WriteString(tB_Ruestzeit.Text);
        w.WriteEndElement();
        w.WriteStartElement("Color_Abruestzeit");
        w.WriteString(tB_Abruestzeit.Text);
        w.WriteEndElement();       
        ...
        ...
        w.WriteEndElement();//Ansicht

        //w.WriteStartElement("Letzter_Zugriff");
        //w.WriteString(tB_Letzter_Zugriff.Text);
        //w.WriteEndElement();
        w.WriteEndElement();//Konfiguration
        w.WriteEndDocument();
        w.Flush();
      }
      finally
      {
        //MessageBox.Show(ex.Message);
        w.Close();
      }//Erzeuge XML mit Writer
    }

Zur Vollständigkeit die XML-Datei:


<?xml version="1.0" encoding="iso-8859-1" ?> 
- <!-- Konfigurationseinstellungen fuer Programm
  --> 
- <Konfiguration>
- <Datenbank>
  <Alias>Oracle10g</Alias> 
  <User>peter</User> 
  <Password>test</Password> 
  </Datenbank>
- <Ansicht>
  <Color_Ruestzeit>Color [A=255, R=128, G=255, B=128]</Color_Ruestzeit> 
  <Color_Auftrag_Produktion>Color [Lime]</Color_Auftrag_Produktion> 
  </Ansicht>
  </Konfiguration>

Grüße von pegasus2

M
456 Beiträge seit 2004
vor 18 Jahren
xmlDoc.Load(Application.StartupPath + "\Konfiguration.Xml");

Es ist doch immer wieder das Selbe 😁
Siehe Posting von mir um 19:54. Ich resigniere ...

I am Jack's smirking revenge.
I am Jack's raging bile duct.
I am Jack's cold sweat.
I am Jack's complete lack of surprise.
I am Jack's broken heart.
I am Jack's wasted life.

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo maxE,

jemanden, der die Bedeutung von PC = Personal Computer = persönlicher Computer ernst nimmt, kannst du nicht wirklich vorwerfen, wenn er nur eine Konfigurationsdatei und nicht eine pro Nutzer ablegt. Auf einem PC in obigem Sinne ist die Nutzerzahl immer gleich eins.

Daten (und seien es Konfigurationsdaten) in Programmverzeichnissen und nicht in Datenverzeichnissen abzulegen, kann man dagegen immer kritisieren - aber es ist nunmal ungemein praktisch (für den Entwickler).

herbivore

M
456 Beiträge seit 2004
vor 18 Jahren

Eine große Windowsschwäche ist, dass der Nutzer dazu verleitet wird, immer als Admin angemeldet zu sein. Viele Sicherheitsprobleme könnten mit einer konsequenten Rechtevergabe gelöst werden.
Man muss daran denken, dass man ein Programm auch mal weitergeben möchte und dieser Nutzer richtet deswegen vielleicht auch mehre Konten ein.
Schreibt man solche Programme wie oben, unterstützt man diese Unart nur noch weiter (Was ja leider auch schon seit Jahren geschieht). Auch dem Kunden/SysAdmin, dem du solche Anwendung übergibst, werden solche Amateurfehler einfach nur verärgern.

Nicht nur ich denke so, sondern auch Microsoft kapiert es so langsam und die Linux/Unix/MacOS Community hat es schon längst begriffen 😉

Übrigens: Longhorn wird nun endlich standardmäßig eingeschränkte Benutzerkonten für User einrichten. Man kann MS eigentlich nur gratulieren, da endlich den Riegel vorzuschieben und mit dem Kompatibilitätsdogma zu brechen. Programme wie von Pegasus2 werden dann - es lebe die Vernunft - nicht mehr funktionieren.

Nochmal kurz: Soll eure Software auch noch für zukünftige Betriebssystemversionen fit sein, dann seht zu, dass sie auch mit eingeschränkten Benutzerkonten zurecht kommt.

I am Jack's smirking revenge.
I am Jack's raging bile duct.
I am Jack's cold sweat.
I am Jack's complete lack of surprise.
I am Jack's broken heart.
I am Jack's wasted life.

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo maxE,

was man z.B. dadurch erreichen kann, dass man im Installationsprogramm dafür sorgt, dass der Benutzer (= Jeder) Schreibrechte für das Anwendungsverzeichnis erhält. 🙂

Versteh mich nicht falsch! Ich will deinen Kampf für gute Software nicht sabotieren. Und ich stimme deiner Ansicht, wie gute Software aussieht, zu. Ich wollte bloß motivieren, wie es dazu kommt, dass Software eben gegen diese Regeln verstößt. Deinem Beitrag entnehme ich, dass dir das durchaus bewußt ist.

Ich finde es einfach verfehlt, den Entwicklern vorzuwerfen einem Dogma zu folgen, dass Microsoft jahrelang verbreitet und vorgelegt hat und erst in letzter Zeit davon abgeht. Wenn ein Konzern wie Microsoft jahrelang selbst Anfängerfehler macht, kann man das einem tatsächlichen Anfänger erst recht nicht ankreiden. An die neue Situation wird sich die Entwicklergemeinde erst langsam gewöhnen.

herbivore

M
456 Beiträge seit 2004
vor 18 Jahren

Hi herbivore!

was man z.B. dadurch erreichen kann, dass man im Installationsprogramm dafür sorgt, dass der Benutzer (= Jeder) Schreibrechte für das Anwendungsverzeichnis erhält. 🙂

Na ja, ich glaube das wäre so mit das schlimmste was in einer Multiuserumgebung passieren könnte😉

Natürlich hat hier Microsoft gepennt.
Und die Hauptprobleme stammen noch aus der Windows 95 - Me Ära.
Wegen Kompatibilitätsgründen hat man das komplette Rechtemanagment untergraben und muss heute mit allen Problemen leben.
Glücklicherweise wird Microsoft da in Zukunft etwa rigider.
Aber ich bitte einfach alle Programmierer nicht mehr in Windows 95 Zeiten stehen zu bleiben und ihre Anwendungen jetzt anzupassen. Der Mehraufwand ist minimal. Seit Windows 2000/XP da ist und die alten Windowsversionen abgelöst hat, sollte man sich einfach ein paar grundlegende Dinge angewöhnen.

Bitte denkt also daran: Eure Anwendungsdaten gehören nicht irgendwo hin, sondern es gibt spezielle Verzeichnisse die dafür vorgesehen sind.

I am Jack's smirking revenge.
I am Jack's raging bile duct.
I am Jack's cold sweat.
I am Jack's complete lack of surprise.
I am Jack's broken heart.
I am Jack's wasted life.

P
120 Beiträge seit 2005
vor 18 Jahren

Habe ja richtig für Aufregung gesorgt. 🙂 Natürlich hat maxE Recht, Konfigurationsdateien sollten niemals in das gleiche Verzeichnis gelegt werden. War für mich einfach nur bequemer das Resultat sofort überprüfen zu können, als jedesmal in den Verästelungen des Explorers zu suchen.

Habe mich selbst auch schon oft darüber aufgeregt, das manche Applikationen sich gar nicht mit eingeschränkten Benutzerrechten starten lassen. Es gibt allerdings viele Einstellungen, die für jederman gültig sein sollen und nicht benutzerabhängig gespeichert werden sollen (siehe u.a. HKEY_LOCAL_MACHINE + HKEY_CURRENT_USER der Registry) und bei eingeschränkten Rechten dennoch gelesen werden können.

M
456 Beiträge seit 2004
vor 18 Jahren

Jup, auch für Benutzereinstellungen, die für alle User gültig sein sollen, gibt es ein Verzeichnis: "C:\Dokumente und Einstellungen\All Users\Anwendungsdaten" (Je nach Sprachversion). Die Verzeichnisse können alle problemlos mit _Environment.GetFolderPath() _ausgelesen werden.
Wie gesagt, ich wollte nur noch mal darauf hinweisen. Auch in Hinblick auf Longhorn erspart ihr euch ne Menge Probleme (wenn es denn irgendwann mal draußen sein sollte 😉 )

I am Jack's smirking revenge.
I am Jack's raging bile duct.
I am Jack's cold sweat.
I am Jack's complete lack of surprise.
I am Jack's broken heart.
I am Jack's wasted life.

1.457 Beiträge seit 2004
vor 18 Jahren

Gibt es eine Möglichkeit auf die Settings von anderen Projekten draufzuzugreifen über die Settings Klasse?

Hintergrund ist folgender:

Meine Anwendung hat einen Dienst, FrontEnd (Windows.Forms) und zur Vereinfachung eine Lib.

Dienst und Anwendung greifen auf die Lib zu. In der Lib ist eine Settings Datei / Klasse. Nun möchte ich aber vom Dienst oder FrontEnd aus auch auf diese Settings Datei / Klasse mind. lesend zugreifen.

Wie kann ich dies ohne großen Aufwand bewerkstelligen? Ohne das ich selber die Konfigurationsdatei auslese und auswerte.

S
8.746 Beiträge seit 2005
vor 18 Jahren

Baue dir doch einfach das .NET 2.0-Konfig-Modell nach. Kostet 5 Min Zeit und geht auch auf 1.1! Da kannst du dann jedes beliebige File (egal wo) laden, also auch fremde. Speichern geht dann auch.

Man nehme:

  1. XSD-Schema mit den Settings
  2. XSD.EXE welches eine Klasse für die Setting generiert
  3. Den XmlSerializer, welches die Setting lädt und speichert.

Fertig ist die Laube. Mache ich nur so. Die App.Config kann nix!

1.457 Beiträge seit 2004
vor 18 Jahren

Ich weiß nicht was du damit meinst. Warum soll ich nochmal das Rad neu erfinden?

M
329 Beiträge seit 2004
vor 18 Jahren

Warum soll ich nochmal das Rad neu erfinden?

Manchmal ist das neue Rad das Bessere 😉

S
8.746 Beiträge seit 2005
vor 18 Jahren

Weil es - wie bereits angedeutet - keine ähnlich flexible Lösung in .NET existiert.

Auch die 2.0-Variante krankt nach wie vor an der Tatsache, dass die Config-Struktur flach ist. Komplexe Strukturen sind nicht abzubilden. Unverständlich, wo nun offenbar xsd.exe bereits hinter den Kulissen werkelt. Warum aber ein festes Schema vorgeben?

Zudem werden Configurations immer auf Anwendungs-Ebene (geht jetzt wenigstens Assembly?) definiert. Was ist wenn ich eine Config pro Modul/Komponente/Klasse brauche? Was ist mit PlugIn-Konfigurationen?

Kurz gesagt: M$ hat in 2.0 eine wirklich mächtige Lösung vermissen lassen und wieder nur eine Easy-To-Use-Lösung für Trivial-Szenarien mit ein paar kleinen Verbesserungen gefrickelt. Wenn ich gemein sein wollte, könnte ich behaupten, die Verbesserungen adressieren vor allen die Probleme des gemeinen Amateur-Programmierers... 🙂

H
59 Beiträge seit 2005
vor 18 Jahren

diverse fragen werden hier beantwortet
MSDN Blogs > Cool Client Stuff > Client Settings FAQ

J
42 Beiträge seit 2006
vor 18 Jahren

Auch wenn ich mich hier als Leichengräber betätige möchte ich noch anmerken, dass man "wirklich mächtige Lösungen" mit SettingValueElement hinkriegen kann. Der Inhalt des Knotens wird direkt als XML gespeichert und kann daher später in Laufzeit dynamisch ausgewertet oder auch serialisiert werden.
Das benutze ich zur Konfiguration meiner Plugins.

B
483 Beiträge seit 2005
vor 17 Jahren

Hallo,

gibt es die Möglichkeit aus dem Setup-Projekt Config-Datei zu ändern?

Gruss,
Boris

W
343 Beiträge seit 2006
vor 17 Jahren

Hallo leute,

Ich habe eine Überraschung erlebt, ich habe eine Pocket Pc-Anwendung erstellt und wollte Wie es im Artikel beschrieben ist, das neue Konfigurationmodell versuchen, habe leider dann festgestellt dass in dem Eigenschaftenfenster der Anwendung die registerkarte "Einstellung(en)" nicht vorhanden ist.

Ist es so normal ?? oder muss ich etwas machen damit es angezeit wird???

MfG

Willy

C#, einfach geil 8)

9 Beiträge seit 2004
vor 17 Jahren

Ich habe mir eine kleine Klasse für das Schreiben/Lesen von Einstellungen geschrieben.

// created on 02.08.2006 at 16:06
using System;
using System.IO;
using System.Xml;

class Settings
{
	private XmlDocument xmlDoc;
	private XmlElement root = null;
	private string xmlFile;
	
	public Settings (string file, bool createNew)
	{
                // Ich programmiere mit Mono/C# unter Linux.
                // Für Windows sollte das angepasst werden.
		string path = Path.Combine (Environment.GetEnvironmentVariable ("HOME"), ".config");
		if (!Directory.Exists (path))
			Directory.CreateDirectory (path);
		
		string appName = Path.GetFileNameWithoutExtension (Environment.GetCommandLineArgs ()[0]);
		path = Path.Combine (path, appName);
		if (!Directory.Exists (path))
			Directory.CreateDirectory (path);
			
		xmlFile = Path.Combine (path, file);
		xmlDoc = new XmlDocument ();
		
		if (File.Exists (xmlFile) & !createNew)
		{
			try
			{
				xmlDoc.Load (file);
				root = xmlDoc.DocumentElement;
			}
			catch (Exception e)
			{
				throw e;
			}
		}
		else 
		{
			XmlDeclaration xmlDec = xmlDoc.CreateXmlDeclaration ("1.0", "UTF-8", "yes");
			xmlDoc.AppendChild (xmlDec);
			xmlDoc.Save (xmlFile);
		}
		
		if (root == null)
		{
			root = xmlDoc.CreateElement ("settings");
			xmlDoc.AppendChild (root);
			xmlDoc.Save (xmlFile);
		}
	}
	
	private XmlNode FindNode (string key, bool createNew)
	{
		if (key != null)
			if (key[0] == '/')
				key = key.Remove (0, 1);
		
		if (key != null)
			if (key[key.Length - 1] == '/')
				key = key.Remove (key.Length - 1, 1);
				
		char[] splitChars = {'/'};
		string[] parts = key.Split (splitChars);

		XmlNode node = root;
		XmlNode child = null;
		
		foreach (string entry in parts)
		{
			child = node.FirstChild;
			do
			{
				if (child == null || child.Name == entry)
					break;
				
				child = child.NextSibling;
			}
			while (child == null);
			
			if (child == null)
			{
				child = xmlDoc.CreateElement (entry);
				node.AppendChild (child);
			}
			node = child;
		}
		return node;
	}
	
	public void Remove (string key)
	{
		XmlNode parent;
		XmlNode node = FindNode (key, false);
		
		while (node != null && node.ChildNodes.Count == 0)
		{
			parent = node.ParentNode;
			parent.RemoveChild (node);
			if (parent == root)
				break;
			node = parent;
		}
		
		xmlDoc.Save (xmlFile);
	}
	
	public void Write (string key, string newValue)
	{
		XmlNode node = FindNode (key, true);
		node.InnerText = newValue;
		xmlDoc.Save (xmlFile);
	}
	
	public void Write (string key, char newValue)
	{
		Write (key, newValue.ToString ());
	}
	
	public void Write (string key, byte newValue)
	{
		Write (key, newValue.ToString ());
	}
	
	public void Write (string key, short newValue)
	{
		Write (key, newValue.ToString ());
	}
	
	public void Write (string key, int newValue)
	{
		Write (key, newValue.ToString ());
	}
	
	public void Write (string key, long newValue)
	{
		Write (key, newValue.ToString ());
	}
	
	public void Write (string key, ushort newValue)
	{
		Write (key, newValue.ToString ());
	}
	
	public void Write (string key, uint newValue)
	{
		Write (key, newValue.ToString ());
	}
	
	public void Write (string key, ulong newValue)
	{
		Write (key, newValue.ToString ());
	}
	
	public void Write (string key, float newValue)
	{
		Write (key, newValue.ToString ());
	}
	
	public void Write (string key, double newValue)
	{
		Write (key, newValue.ToString ());
	}
	
	public void Write (string key, DateTime newValue)
	{
		Write (key, newValue.Ticks.ToString ());
	}	
	
	public string Read (string key, string defValue)
	{
		XmlNode node = FindNode (key, false);
		if (node != null && node.InnerText != null)
			return node.InnerText;
		else
			return defValue;
	}
	
	public char Read (string key, char defValue)
	{
		string result = Read (key, defValue.ToString ());
		try
		{
			return Convert.ToChar (result);
		}
		catch
		{
			return defValue;
		}
	}
	
	public byte Read (string key, byte defValue)
	{
		string result = Read (key, defValue.ToString ());
		try
		{
			return Convert.ToByte (result);
		}
		catch
		{
			return defValue;
		}
	}
	
	public short Read (string key, short defValue)
	{
		string result = Read (key, defValue.ToString ());
		try
		{
			return Convert.ToInt16 (result);
		}
		catch
		{
			return defValue;
		}
	}
	
	public int Read (string key, int defValue)
	{
		string result = Read (key, defValue.ToString ());
		try
		{
			return Convert.ToInt32 (result);
		}
		catch
		{
			return defValue;
		}
	}
	
	public long Read (string key, long defValue)
	{
		string result = Read (key, defValue.ToString ());
		try
		{
			return Convert.ToInt64 (result);
		}
		catch
		{
			return defValue;
		}
	}
	
	public ushort Read (string key, ushort defValue)
	{
		string result = Read (key, defValue.ToString ());
		try
		{
			return Convert.ToUInt16 (result);
		}
		catch
		{
			return defValue;
		}
	}
	
	public uint Read (string key, uint defValue)
	{
		string result = Read (key, defValue.ToString ());
		try
		{
			return Convert.ToUInt32 (result);
		}
		catch
		{
			return defValue;
		}
	}
	
	public ulong Read (string key, ulong defValue)
	{
		string result = Read (key, defValue.ToString ());
		try
		{
			return Convert.ToUInt64 (result);
		}
		catch
		{
			return defValue;
		}
	}
	
	public bool Read (string key, bool defValue)
	{
		string result = Read (key, defValue.ToString ());
		try
		{
			return Convert.ToBoolean (result);
		}
		catch
		{
			return defValue;
		}
	}
	
	public float Read (string key, float defValue)
	{
		string result = Read (key, defValue.ToString ());
		try
		{
			return Convert.ToSingle (result);
		}
		catch
		{
			return defValue;
		}
	}

	public double Read (string key, double defValue)
	{
		string result = Read (key, defValue.ToString ());
		try
		{
			return Convert.ToDouble (result);
		}
		catch
		{
			return defValue;
		}
	}
	
	public DateTime Read (string key, DateTime defValue)
	{
		string result = Read (key, defValue.Ticks.ToString ());
		try
		{
			return new DateTime (Convert.ToInt64 (result));
		}
		catch
		{
			return defValue;
		}
	}
}

Gruß, Burgpflanze

A
217 Beiträge seit 2006
vor 17 Jahren

Baue dir doch einfach das .NET 2.0-Konfig-Modell nach. Kostet 5 Min Zeit und geht auch auf 1.1!

Das hört sich SEHR interessant an!
Hast du da ein Beispiel zu?
Ich bin da leider noch nicht so firm drin.

Hintergrund:
Ich möchte Parameter, welche ich bisher in INI-Dateien abgelegt habe nun gerne nach dem neuen 2.0er-Schema ablegen.

[pre][SYSTEM]
TEST=Wert

[DEFAULTS]
AAA=Wert1
BBB=Wert2
CCC=Wert3[/pre]

Was ich nun benötige ist, dass ich weiterhin Sektionen verwenden kann.
Die Sektion "DEFAULTS" zum Beispiel muss ich iterieren.
Ich weiß also nie genau, welche Werte mich erwarten.
Soweit ich bisher rausgefunden habe, geht das leider nicht, oder?

Deshalb interessiert mich dein Prizip.
Vielleicht kann ich das dazu verwenden?

Was auch toll wäre, wäre das einfache ablegen einfacher Werte wie zum Beispiel diese Liste

[pre][LISTE]
WertA
WertB
WertC
[/pre]

um sie beim Start der Anwendung auch einfach zu iterieren.

Kann mir da jemand helfen?

Gruß,
AtzeX

I
14 Beiträge seit 2007
vor 16 Jahren

Erst mal wunderbaren Dank für des tut hat mir super weitergeholfen.

Des Problem vor dem ich jetzt noch stehe ist das ich meine geänderten Werte nicht abspeichern kann denn er sagt mir "Eine Eigenschaft oder ein Indexer ... kann nicht zugewiesen werden --- sie sind schreibgeschützt. Wie krieg ich denn Schreibschutz denn raus?

Gruß Iginaz

[EDIT]Ok hab meinen Fehler wollte es als Scope Applikation machen aber die sind zur laufzeit schreibgeschützt. Man kann ja nur die User ändern.[/EDIT]

A
24 Beiträge seit 2009
vor 14 Jahren

Hi,

zu dem tollen Konfigurationsmodell habe ich noch eine Frage: Warum werden die Konfigurationsdateien nicht wie gewohnt in %APPDATA% sondern im Verzeichnis C:\Dokumente und Einstellungen&lt;User Name>\Lokale Einstellungen\Anwendungsdaten&lt;Anwendung> abgelegt? Der neue Ort macht die Umgebungsvariable %APPDATA% quasi unbrauchbar. Welche Möglichkeiten hat man denn sonst noch möglichst programatisch auf das neue Konfigurationsverzeichnis zuzugreifen?

Danke & Grüße

A
24 Beiträge seit 2009
vor 14 Jahren

Hat niemand eine Erklärung dafür, warum jetzt zwei Verzeichnisse für Anwendungsdaten existieren?

%APPDATA% C:\Dokumente und Einstellungen&lt;User Name>\Anwendungsdaten&lt;Anwendung>
.NET Konfigurationsmodell C:\Dokumente und Einstellungen&lt;User Name>\Lokale Einstellungen\Anwendungsdaten&lt;Anwendung>

M
120 Beiträge seit 2009
vor 14 Jahren

Die beiden existieren schon sehr lange. Die Sachen in Lokale Einstellungen\Anwendungsdaten werden bei Active Directory-Nutzung im Gegensatz zu denen in Anwendungsdaten nur lokal und nicht auch auf dem Server gespeichert. Für beide steht bei SpecialFolder etwas zur Verfügung.
Warum hier lokale Einstellungen verwendet wird kann man nur vermuten aber eventuell soll der Server nicht mit den Einstellungsdateien der verschiedenen Versionen zugemüllt werden 😉.

I
279 Beiträge seit 2008
vor 14 Jahren

Huhu,

Wie kann ich denn verhindern das bei jeder Änderung der Versionsnummer eines neues Verzeichnis für die Konfiguration angelegt wird?

T
381 Beiträge seit 2009
vor 12 Jahren

Es gibt 2 Versionsnummern:

[assembly: AssemblyVersion("1.4.4.0")] // Änderung führt zu neuem Verzeichnis für die COnfig
[assembly: AssemblyFileVersion("1.6.0.0")] // Dateiversion der Assembly. Änderung hat keinen Einfluss auf die Config

Mich interessiert wie man an den Pfad der Config ran kommt.

D
615 Beiträge seit 2009
vor 12 Jahren

Hallo

Ich denke du suchst das :

Pfad der gespeicherten Einstellungen (app.config) finden??

Beste Grüsse

Diräkt

5.742 Beiträge seit 2007
vor 12 Jahren