myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
   » Plugin für Firefox
   » Plugin für IE
   » Gadget für Windows
» Regeln
» Wie poste ich richtig?
» Datenschutzerklärung
» wbb-FAQ

Mitglieder
» Liste / Suche
» Stadt / Anleitung dazu
» Wer ist wo online?

Angebote
» ASP.NET Webspace
» Bücher
» Zeitschriften
   » dot.net magazin
» Accessoires

Ressourcen
» .NET-Glossar
» guide to C#
» openbook: Visual C#
» openbook: OO
» .NET BlogBook
» MSDN Webcasts
» Search.Net

Team
» Kontakt
» Übersicht
» Wir über uns
» Bankverbindung
» Impressum

» Unsere MiniCity
MiniCity
» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Knowledge Base » Artikel » [Tutorial] Konfigurationsmodell im .NET Framework
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | An Freund senden | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

[Tutorial] Konfigurationsmodell im .NET Framework

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
Noodles
myCSharp.de-Poweruser/ Experte

Dabei seit: 08.02.2004
Beiträge: 4.646
Herkunft: Leipzig


Noodles ist offline

[Tutorial] Konfigurationsmodell im .NET Framework

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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-Code:
<?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\MyCsharpConfiguratio
nSamp_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-Code:
<?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:

C#-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();
            }
        }
    }
}
30.04.2005 21:15 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
pegasus2 pegasus2 ist männlich
myCSharp.de-Mitglied

Dabei seit: 31.03.2005
Beiträge: 120
Entwicklungsumgebung: VS 2005, Delphi 2-7


pegasus2 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von pegasus2 am 12.05.2005 15:12.

12.05.2005 14:59 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
KRambo KRambo ist männlich
myCSharp.de-Mitglied

Dabei seit: 29.08.2004
Beiträge: 352
Entwicklungsumgebung: Visual Studio 2005


KRambo ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 unglücklich
12.05.2005 15:53 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Noodles
myCSharp.de-Poweruser/ Experte

Dabei seit: 08.02.2004
Beiträge: 4.646
Herkunft: Leipzig

Themenstarter Thema begonnen von Noodles

Noodles ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von pegasus2:
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\<username>\Lokale Einstellungen\Anwendungsdaten

Zitat von pegasus2:
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?
12.05.2005 18:13 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
maxE maxE ist männlich
myCSharp.de-Mitglied

Dabei seit: 27.04.2004
Beiträge: 456
Entwicklungsumgebung: SharpDevelop
Herkunft: Sachsen


maxE ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
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.
12.05.2005 19:54 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
pegasus2 pegasus2 ist männlich
myCSharp.de-Mitglied

Dabei seit: 31.03.2005
Beiträge: 120
Entwicklungsumgebung: VS 2005, Delphi 2-7


pegasus2 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Erst mal vielen Dank für die Resonanz smile , 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:

C#-Code:
    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:

C#-Code:
<?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

Dieser Beitrag wurde 4 mal editiert, zum letzten Mal von pegasus2 am 13.05.2005 12:53.

12.05.2005 22:06 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
maxE maxE ist männlich
myCSharp.de-Mitglied

Dabei seit: 27.04.2004
Beiträge: 456
Entwicklungsumgebung: SharpDevelop
Herkunft: Sachsen


maxE ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

C#-Code:
xmlDoc.Load(Application.StartupPath + "\Konfiguration.Xml");

Es ist doch immer wieder das Selbe großes Grinsen
Siehe Posting von mir um 19:54. Ich resigniere ...
12.05.2005 23:08 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Team (Admin)

images/avatars/avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.001
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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
12.05.2005 23:27 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
maxE maxE ist männlich
myCSharp.de-Mitglied

Dabei seit: 27.04.2004
Beiträge: 456
Entwicklungsumgebung: SharpDevelop
Herkunft: Sachsen


maxE ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 Augenzwinkern

Ü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.
13.05.2005 00:25 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Team (Admin)

images/avatars/avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.001
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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
13.05.2005 07:40 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
maxE maxE ist männlich
myCSharp.de-Mitglied

Dabei seit: 27.04.2004
Beiträge: 456
Entwicklungsumgebung: SharpDevelop
Herkunft: Sachsen


maxE ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi herbivore!

Zitat:
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önnteAugenzwinkern

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.
13.05.2005 11:36 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
pegasus2 pegasus2 ist männlich
myCSharp.de-Mitglied

Dabei seit: 31.03.2005
Beiträge: 120
Entwicklungsumgebung: VS 2005, Delphi 2-7


pegasus2 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Habe ja richtig für Aufregung gesorgt. smile 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.
13.05.2005 12:45 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
maxE maxE ist männlich
myCSharp.de-Mitglied

Dabei seit: 27.04.2004
Beiträge: 456
Entwicklungsumgebung: SharpDevelop
Herkunft: Sachsen


maxE ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 Augenzwinkern )
13.05.2005 16:21 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegt mehr als ein Monat.
Timur Zanagar Timur Zanagar ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-3412.jpg


Dabei seit: 10.11.2004
Beiträge: 1.457


Timur Zanagar ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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.
11.07.2005 16:36 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
svenson svenson ist männlich
myCSharp.de-Poweruser/ Experte

Dabei seit: 15.04.2005
Beiträge: 8.746
Entwicklungsumgebung: Visual Studio .NET 2003
Herkunft: Berlin


svenson ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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!
11.07.2005 17:23 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Timur Zanagar Timur Zanagar ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-3412.jpg


Dabei seit: 10.11.2004
Beiträge: 1.457


Timur Zanagar ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich weiß nicht was du damit meinst. Warum soll ich nochmal das Rad neu erfinden?
12.07.2005 10:44 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Michael Schuler Michael Schuler ist männlich
myCSharp.de-Mitglied

Dabei seit: 29.08.2004
Beiträge: 329
Entwicklungsumgebung: VS 2008
Herkunft: Zürich, Schweiz


Michael Schuler ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
Warum soll ich nochmal das Rad neu erfinden?

Manchmal ist das neue Rad das Bessere Augenzwinkern
12.07.2005 11:32 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
svenson svenson ist männlich
myCSharp.de-Poweruser/ Experte

Dabei seit: 15.04.2005
Beiträge: 8.746
Entwicklungsumgebung: Visual Studio .NET 2003
Herkunft: Berlin


svenson ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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... smile

Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von svenson am 12.07.2005 11:55.

12.07.2005 11:52 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 6 Monate.
harrylask harrylask ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.07.2005
Beiträge: 59
Herkunft: Salzburg


harrylask ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

diverse fragen werden hier beantwortet
 MSDN Blogs > Cool Client Stuff > Client Settings FAQ
26.01.2006 07:58 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegt mehr als ein Monat.
Jabberwocky
myCSharp.de-Mitglied

Dabei seit: 11.03.2006
Beiträge: 42


Jabberwocky ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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.
11.03.2006 13:13 Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegt mehr als ein Monat.
boco25 boco25 ist männlich
myCSharp.de-Mitglied

Dabei seit: 13.01.2005
Beiträge: 483
Herkunft: Frankfurt


boco25 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

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

Gruss,
Boris
11.04.2006 14:36 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 3 Monate.
willy willy ist männlich
myCSharp.de-Mitglied

Dabei seit: 24.04.2006
Beiträge: 343
Entwicklungsumgebung: Visual Studio .NET 2008
Herkunft: München


willy ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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
21.07.2006 14:18 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Burgpflanze
myCSharp.de-Mitglied

images/avatars/avatar-2270.jpg


Dabei seit: 15.03.2004
Beiträge: 9
Entwicklungsumgebung: VS 2008
Herkunft: Dresden


Burgpflanze ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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

C#-Code:
// 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;
        }
    }
}
02.08.2006 18:13 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
AtzeX
myCSharp.de-Mitglied

Dabei seit: 30.05.2006
Beiträge: 214


AtzeX ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von svenson:
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.

[SYSTEM]
TEST=Wert

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

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

[LISTE]
WertA
WertB
WertC

um sie beim Start der Anwendung auch einfach zu iterieren.

Kann mir da jemand helfen?

Gruß,
AtzeX

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von AtzeX am 18.08.2006 14:41.

18.08.2006 14:41 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 8 Monate.
iginaz iginaz ist männlich
myCSharp.de-Mitglied

Dabei seit: 23.04.2007
Beiträge: 14
Entwicklungsumgebung: Visual Studio 2005/ 2008


iginaz ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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]
23.04.2007 17:07 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 2 Jahre.
Anonymous Developer
myCSharp.de-Mitglied

Dabei seit: 22.01.2009
Beiträge: 24


Anonymous Developer ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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\<User Name>\Lokale Einstellungen\Anwendungsdaten\<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

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Anonymous Developer am 27.04.2009 18:24.

25.04.2009 21:58 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Anonymous Developer
myCSharp.de-Mitglied

Dabei seit: 22.01.2009
Beiträge: 24


Anonymous Developer ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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

%APPDATA% C:\Dokumente und Einstellungen\<User Name>\Anwendungsdaten\<Anwendung>
.NET Konfigurationsmodell C:\Dokumente und Einstellungen\<User Name>\Lokale Einstellungen\Anwendungsdaten\<Anwendung>
05.05.2009 17:34 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Marsti Marsti ist männlich
myCSharp.de-Mitglied

Dabei seit: 02.05.2009
Beiträge: 120
Entwicklungsumgebung: Visual Studio


Marsti ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

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 ;).
05.05.2009 18:34 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 9 Monate.
iced-t89
myCSharp.de-Mitglied

Dabei seit: 19.07.2008
Beiträge: 279


iced-t89 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Huhu,

Wie kann ich denn verhindern das bei jeder Änderung der Versionsnummer eines neues Verzeichnis für die Konfiguration angelegt wird?
18.02.2010 11:13 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegt mehr als ein Jahr.
Tarion Tarion ist männlich
myCSharp.de-Mitglied

images/avatars/avatar-91.gif


Dabei seit: 23.03.2009
Beiträge: 381
Entwicklungsumgebung: VS2010 Ultimate


Tarion ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Es gibt 2 Versionsnummern:

Zitat:
[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.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Tarion am 27.03.2011 19:29.

27.03.2011 19:29 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Diräkt Diräkt ist männlich
myCSharp.de-Mitglied

Dabei seit: 05.11.2009
Beiträge: 566
Entwicklungsumgebung: VS 2010
Herkunft: Schweiz


Diräkt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo

Ich denke du suchst das :

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

Beste Grüsse

Diräkt
30.03.2011 17:30 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 5 Monate.
winSharp93 winSharp93 ist männlich
myCSharp.de-Team (Moderation)

images/avatars/avatar-2918.png


Dabei seit: 19.01.2007
Beiträge: 5.742
Herkunft: Stuttgart


winSharp93 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

15.09.2011 18:13 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 9 Jahre.
Der letzte Beitrag ist älter als 3 Jahre.
Antwort erstellen


© Copyright 2003-2014 myCSharp.de-Team. Alle Rechte vorbehalten. 22.10.2014 11:34