## 15.3 Konfigurationsdateien ### 15.3.1 Einführung Konfigurationsdateien können das Laufzeitverhalten einer Anwendung beeinflussen, ohne dass die Anwendung neu kompiliert werden muss. In einer Konfigurationsdatei werden Vorgaben getroffen, die beim Starten einer Anwendung von der Common Language Runtime (CLR) ausgewertet werden. Darüber hinaus ist auch während der Laufzeit der Zugriff auf eine Konfigurationsdatei mittels Programmcode möglich. Doch was beschreiben Konfigurationsdateien? Letztendlich handelt es sich dabei um Daten, die von einer Anwendung während der Ausführung benötigt werden. Dabei kann es sich um Daten handeln, die sicherstellen, dass der Zustand einer Anwendung bei einem Neustart genau so restauriert wird, wie es beim Schließen der Anwendung der Fall war. Es kann sich um Variableninhalte handeln, um Verbindungszeichenfolgen für ADO.NET oder auch um die Angabe darüber, welche Version einer bestimmten Assembly aus dem Global Assembly Cache (GAC) geladen werden soll. In der Vor-.NET-Zeit diente die Registry des Windows-Betriebssystems als globaler Datenspeicher der Anwendungen und des Rechners, Anwendungsdaten wurden oft in INI-Dateien beschrieben. Mit den .NET-Konfigurationsdateien ist praktisch das Ende des proprietären Datenspeichers Registry eingeläutet worden, und INI-Dateien sind zur Bedeutungslosigkeit degradiert. Sicher wird es noch viele Jahre dauern, bis auf beide Elemente vollständig verzichtet werden kann, denn zu viele Anwendungen sind elementar abhängig davon. Aber der weitere Weg ist bereits vorgezeichnet. Es gibt mehrere verschiedene Konfigurationsdateien, die unter .NET eine mehr oder weniger entscheidende Rolle einnehmen. Wir haben uns im Rahmen dieses Buches mit Anwendungen auf der lokalen Maschine beschäftigt, deshalb können wir eine Aufzählung auch auf drei Typen beschränken: Anwendungskonfigurationsdateien Herausgeberrichtliniendateien die Maschinenkonfigurationsdatei (machine.config) In erster Linie werden wir uns in diesem Abschnitt mit den Anwendungskonfigurationsdateien beschäftigen. Dieser Typ splittet sich in zwei Gruppen auf, die unterschiedliche Daten beschreiben: Anwendungsdaten, die für die gesamte Anwendung gültig und unabhängig vom jeweiligen Benutzer sind Daten, die benutzerspezifisch sind Das alles werden wir im weiteren Verlauf dieses Kapitels noch genauer untersuchen. ### 15.3.2 Die verschiedenen Konfigurationsdateien Bevor wir uns exemplarisch eine Konfigurationsdatei ansehen, sollten wir uns darüber bewusst sein, dass es unter .NET mehrere verschiedene Konfigurationsdateien gibt, die durchaus auch identische Elemente aufweisen können. Typisch für alle Konfigurationsdateien ist die Dateierweiterung .config. Der Inhalt wird durch XML beschrieben. Verschaffen wir uns zuerst einen allgemeinen Überblick. Anwendungskonfigurationsdatei: Falls einer .NET-Anwendung eine Anwendungskonfigurationsdatei zugeordnet wird, ist diese immer im Stammverzeichnis der Anwendung zu finden. Der Name einer Konfigurationsdatei setzt sich aus dem Namen der Programmdatei und dem Suffix .config zusammen. Heißt die Programmdatei MyApplication.exe, heißt die Konfigurationsdatei demnach MyApplication.exe.config. Eine Konfigurationsdatei, die dieser Namenskonvention folgt, muss im Stammverzeichnis der Anwendung gespeichert werden und wird vor dem Start der Anwendung von der CLR ausgewertet. Die Einstellungen in der Anwendungskonfigurationsdatei sind daher für die Anwendung spezifisch und haben keine Auswirkungen auf andere Anwendungen. Publisherrichtliniendatei (Herausgeberrichtliniendatei): Dieser Konfigurationsdateityp kann zusammen mit dem Update oder Service Pack einer globalen Assembly ausgeliefert werden. Eine Publisherrichtliniendatei, in der .NET-Dokumentation auch als Herausgeberrichtliniendatei bezeichnet, kann nur vom Entwickler einer globalen Assembly für eine bestimmte Assemblierung bereitgestellt werden. Sie hat die Aufgabe, den Zugriff der Anwendungen, die normalerweise die Dienste der »alten« globalen Assembly in Anspruch nehmen würden, auf eine neue Version umzuleiten. Damit hat zumindest der Hersteller der Komponente das Seinige getan, um zu vermeiden, dass Anwendungen weiterhin eine möglicherweise fehlerhafte Version benutzen. Weitere Informationen, insbesondere das Erzeugen einer Publisherrichtliniendatei, finden Sie unter »Erstellen einer Publisherrichtliniendatei« in der Online-Hilfe. Maschinenkonfigurationsdatei: Der Name dieser Konfigurationsdatei lautet machine.config. Haben Sie bei der Installation keine anderen Vorgaben getroffen, befindet sich diese Datei in folgendem Ordner: \Windows\Microsoft .NET\Framework\v4.0.30319\Config In der Computerkonfigurationsdatei sind viele .NET betreffende Einstellungen des lokalen Rechners zentral beschrieben. Daher ist diese Konfigurationsdatei auch sehr groß und erscheint mit ihren zahllosen Einträgen, die sich auf das gesamte Laufzeitverhalten von .NET-Anwendungen und -Komponenten auswirken, unüberschaubar. #### Aufrufreihenfolge der Konfigurationsdateien Die Suche nach den Konfigurationsdateien erfolgt dabei in der folgenden Reihenfolge:
1. | Anwendungskonfigurationsdatei
2. | Herausgeberrichtliniendatei (Publisherrichtliniendatei)
3. | Maschinenkonfigurationsdatei
Wie schon erwähnt wurde, lässt sich mit einer Konfigurationsdatei auch steuern, welche Version einer bestimmten globalen Assembly eine Anwendung aufrufen soll. Wie das gemacht wird, zeige ich Ihnen später. Wird die Anwendung gestartet, ist zunächst das Manifest ausschlaggebend dafür, welche Version der Assembly geladen werden soll. Die Laufzeitumgebung merkt sich die Version und sucht anschließend nach einer eventuell vorhandenen Anwendungskonfigurationsdatei. Gibt es eine solche im Anwendungsverzeichnis und enthält sie einen Eintrag, der die Umleitung zu einer anderen Version beschreibt, so überschreibt der Eintrag in der Anwendungskonfigurationsdatei den Eintrag im Manifest. Nach der Suche und der Auswertung der Anwendungskonfigurationsdatei interessiert sich die Laufzeitumgebung für eine möglicherweise existierende Publisherrichtliniendatei. Hat der Entwickler der globalen Assembly eine solche bereitgestellt und ist sie im GAC installiert, überschreibt deren Versionsangabe diejenige, die bis zu diesem Zeitpunkt gültig war. Im letzten Schritt durchforstet die Laufzeitumgebung die Maschinenkonfigurationsdatei, die im Gegensatz zu den beiden vorher aufgeführten Dateien nicht optional ist. Hat der Anwender in machine.config eine Versionsumleitung eingetragen (dazu sind administrative Rechte notwendig), gilt diese vor allen anderen. Entscheidend dafür, auf welche Assembly-Version die Anwendung zugreift, ist der zuletzt gefundene Eintrag. Sollen alle Anwendungen grundsätzlich mit einer bestimmten Version arbeiten, genügt ein Eintrag in die Maschinenkonfigurationsdatei. Auf eine Anwendungskonfigurationsdatei kann in diesem Fall verzichtet werden – es sei denn, von der Anwendungskonfigurationsdatei werden andere Vorgaben oder Einstellungen beschrieben, die nichts mit dem Versionsaufruf zu tun haben. Es könnte auch passieren, dass in der Maschinenkonfigurationsdatei die Umleitung auf eine bestimmte Version angegeben ist, die sich aber als nicht abwärtskompatibel für eine ganz bestimmte Anwendung erweist, während andere Anwendungen problemlos damit zusammenarbeiten können. Dann besteht die Möglichkeit, in der Anwendungskonfigurationsdatei der betroffenen Anwendung den Automatismus der Versionsumleitung abzuschalten. ### 15.3.3 Struktur einer Anwendungskonfigurationsdatei Da eine Anwendungskonfigurationsdatei optional ist, muss sie einem Programm ausdrücklich hinzugefügt werden. Sie können dazu das Visual Studio 2010 benutzen, Sie können die Anwendungsdatei einer .NET-Anwendung aber auch erst nach deren Installation bereitstellen. Im einfachsten Fall schreiben Sie den gewünschten XML-Code mit dem MS-Editor oder einem anderen, beliebigen ASCII-Editor. Anschließend speichern Sie die Textdatei, also die XML-Datei mit dem vorgeschriebenen Bezeichner im Anwendungsverzeichnis. Das ist schon alles. Wir wollen nun zum ersten Mal mit Visual Studio 2010 eine Konfigurationsdatei einem Projekt hinzufügen. Markieren Sie dazu im Projektmappen-Explorer das Projekt, öffnen Sie dessen Kontextmenü, und wählen Sie Hinzufügen... • Neues Element hinzufügen. Im nächsten Schritt markieren Sie im Dialogfenster den Typ Anwendungskonfigurationsdatei und bestätigen die Auswahl. Die Projektdateien werden danach um die Datei App.config ergänzt. Den Namen App.config dürfen Sie nicht ändern, weil der Compiler nur eine Datei mit diesem Namen als spätere Anwendungskonfigurationsdatei interpretiert. Bei der Kompilierung des Projekts wird aus App.config automatisch der Dateiname generiert, der der Namenskonvention entspricht. Im Arbeitsbereich der Entwicklungsumgebung wird ein neues Fenster mit dem Inhalt der Datei App.config angezeigt. Sie enthält bereits den elementarsten XML-Code:
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    </configuration>
Mit der ersten Zeile, die als XML-Deklaration oder auch als Prolog bezeichnet wird, wird der Einstiegspunkt in das Dokument festgelegt. Neben der Versionsnummer wird auch der zum Lesen des Dokuments verwendete Zeichensatz, hier UTF-8, beschrieben. Jedes XML-Dokument hat ein sogenanntes Stammelement. Bei allen Konfigurationsdateien ist es das <configuration>-Element. Alle Informationen, die zwischen dem einleitenden und dem ausleitenden Tag stehen und ihrerseits selbst Elemente sind, werden dazu benutzt, die Anwendung zu konfigurieren. Ich möchte Ihnen nun eine Konfigurationsdatei zeigen, die nicht nur den erforderlichen Strukturrahmen aufweist, sondern gleichzeitig auch bereits Informationen in sich birgt.
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
        <sectionGroup name="userSettings" ...>
           <section name="AppConfigSample.Properties.Settings" .../>
        </sectionGroup>
        <sectionGroup name="applicationSettings" ...>
           <section name="AppConfigSample.Properties.Settings" .../>
        </sectionGroup>
      </configSections>
      <appSettings>
        <add key="Test" value="123"/>
      </appSettings>
      <userSettings>
        <AppConfigSample.Properties.Settings>
          <setting name="Variable1" serializeAs="String">
            <value>Hallo Andreas!</value>
          </setting>
        </ AppConfigSample.Properties.Settings>
      </userSettings>
      <applicationSettings>
        <AppConfigSample.Properties.Settings>
          <setting name="Variable2" serializeAs="String">
            <value>Hallo Leute!</value>
          </setting>
        </ AppConfigSample.Properties.Settings>
      </applicationSettings>
    </configuration>
Ich habe in dieser Konfigurationsdatei sehr viel kürzen müssen, denn selbst im Codeeditor ist die gesamte Konfigurationsdatei unüberschaubar. Für die folgenden Betrachtungen spielt das aber keine Rolle. Zudem dürfen Sie das Beispiel auch nicht so verstehen, dass ich Ihnen alle denkbaren Möglichkeiten aufzeigen möchte. Ich möchte mich vielmehr auf ein paar wenige Merkmale konzentrieren. Wenn Sie möchten, können Sie sich die komplette Konfigurationsdatei ansehen. Sie ist im Beispielprogramm AppConfigDemo zu finden, das wir gleich besprechen werden. Innerhalb von <configuration> sind vier Sektionen definiert: <configSections> <appSettings> <userSettings> <applicationSettings> Diesen Abschnitten kommt eine besondere Bedeutung zu. In der Erklärung kurzfassen kann ich mich, was den Abschnitt <configSections> angeht. Dieser beschreibt nur die beiden untergeordneten Sektionen <applicationSettings> und <userSettings>. Die Notation in den beiden Abschnitten <applicationSettings> und <userSettings> ist identisch. Zunächst wird ein neuer untergeordneter Abschnitt eröffnet, der eine Klasse angibt, hier zum Beispiel:
    AppConfigDemo.Properties.Settings
Die Klasse heißt Settings, der Namespace AppConfigDemo.Properties. Namespace und Klasse werden von Visual Studio 2010 automatisch erzeugt. Die Klasse Settings definiert dabei hauptsächlich Eigenschaftsmethoden, um den Zugriff auf die Daten zu ermöglichen, die in der Konfigurationsdatei abgelegt sind. Die untergeordneten <setting>-Elemente beschreiben mit dem Attribut name den Bezeichner der gespeicherten Variablen, serializeAs gibt den Datentyp an. Meist werden die Daten als Zeichenfolge serialisiert, ansonsten sind auch noch xml, binary und custom mögliche Alternativen. Das Tag <value> schließlich beschreibt den gespeicherten Wert. #### Der Abschnitt »<applicationSettings>« Benutzerunabhängige Daten sind in der Sektion <applicationSettings> festgelegt. Alle Informationen, die dieser Abschnitt beschreibt, gelten uneingeschränkt für jeden Benutzer der Anwendung. Im Beispiel oben wird nur eine Dateninformation in diesem Abschnitt festgelegt, die die Bezeichnung Variable2 hat und die Zeichenfolge Hallo Leute! beschreibt. Variable2 kann beim Starten der Anwendung ausgewertet und von der laufenden Anwendung weiterverarbeitet werden. Solange sich nichts am Inhalt von Variable2 ändert, käme das der Deklaration einer gleichnamigen Variablen im Code gleich. Sollte jedoch ein abweichender Wert wünschenswert sein, kann dieser in der Konfigurationsdatei geändert werden, ohne dass eine Neukompilierung erforderlich ist. Ein besonderes Charakteristikum von <applicationSettings> ist, dass sich die Werte nicht mittels Code zur Laufzeit editieren lassen. #### Der Abschnitt »<userSettings>« <applicationSettings> ist denkbar ungeeignet, um benutzerspezifische Einstellungen zu speichern. Abgesehen davon, dass die Größe der Konfigurationsdatei bei steigender Benutzeranzahl schnell wächst, würde der Inhalt auch jedem anderen Benutzer offengelegt wie ein Buch. Deshalb werden benutzereigene Einstellungen in der Sektion <userSettings> der Anwendungskonfigurationsdatei beschrieben. Daten, die hier eingetragen werden, gelten als Standardwerte für jeden Anwender. Kommt es zu einer Änderung der Daten, werden diese in einer Datei mit dem Namen user.config im jeweiligen Windows-Benutzerprofil unter Dokumente und Einstellungen\<Benutzer>\Lokale Einstellungen\Anwendungsdaten\<Firma>\ <Anwendung> gespeichert. Daraus können Sie auch entnehmen, dass im Gegensatz zu <applicationSettings> die Daten, die im Abschnitt <userSettings> definiert sind, mittels Code verändert werden können. #### Der Abschnitt »<appSettings>« <appSettings> erfüllt die gleiche Aufgabe wie die Sektion <applicationSettings>, kann jedoch aus dem Code der laufenden Anwendung heraus editiert werden. ### 15.3.4 Anwendungskonfigurationsdatei mit Visual Studio 2010 bereitstellen Eine Konfigurationsdatei wie die oben beschriebene müssen Sie natürlich nicht mit dem MS-Editor oder ähnlichen Programmen mühevoll selbst schreiben. Greifen Sie besser auf die Fähigkeiten von Visual Studio 2010 zurück. Hier klicken, um das Bild zu vergrößern Abbildung 15.14 Festlegen der Konfigurationseinstellungen in Visual Studio 2010 Doppelklicken Sie dazu auf den Knoten Properties im Projektmappen-Explorer. Im Eigenschaftsdialog der Anwendung markieren Sie die Lasche Einstellungen. In dem sich daraufhin öffnenden Fenster können Sie Einträge für die Abschnitte <userSettings> und <applicationSettings> vornehmen. In der Spalte Name tragen Sie den Namen der Variablen ein, und unter Typ legen Sie deren Datentyp fest. Ob es sich um eine allgemeine oder um eine benutzerspezifische Variable handelt, wählen Sie aus der Liste aus, die der Spalte Bereich zugeordnet ist. In der letzten Spalte können Sie auch den Startwert der Variablen bestimmen. Eine Vorgabe ist hier nicht notwendig. Abbildung 15.14 zeigt die Einstellungen für die weiter oben gezeigte Anwendungskonfigurationsdatei. Beim Schließen des Editors werden Sie dazu aufgefordert, die vorgenommenen Einträge zu speichern. Das geschieht natürlich in der Datei App.config, die automatisch hinzugefügt wird, falls es in dem Projekt noch keine gibt. Damit sind aber auch schon die Möglichkeiten des Editors erschöpft. Möchten Sie noch weitere Sektionen festlegen, beispielsweise <appSettings>, öffnen Sie App.config und nehmen diese Ergänzung manuell vor. Dabei werden Sie auch durch eine IntelliSense-Hilfe unterstützt. ### 15.3.5 Einträge der Anwendungskonfigurationsdatei auswerten Jetzt wollen wir uns auch sofort anhand eines Beispiels die Auswertung einer Konfigurationsdatei ansehen. Im folgenden Beispielprogramm werden alle drei Sektionen (<appSettings>, <applicationSettings> und <userSettings>) ausgelesen und darüber hinaus auch den Variablen in <appSettings> und <userSettings> neue Werte übergeben. <applicationSettings> scheidet bekanntlich im letzten Schritt aus, da Inhalte dieser Sektion nicht per Code verändert werden können.
    // --------------------------------------------------------
    // Beispiel: ...\Kapitel 15\AppConfigSample
    // --------------------------------------------------------
    // zusätzliche Namespaces
    using AppConfigSample.Properties;
    using System.Configuration;
    using System.Collections.Specialized;
    class Program {
      static void Main(string[] args) {
        // <userSettings> und <applicationSettings> auswerten
        Settings setting = new Settings();
        string variable1 = setting.Variable1;
        string variable2 = setting.Variable2;
        Console.WriteLine("Variable1 = {0}", variable1);
        Console.WriteLine("Variable2 = {0}", variable2);
        // <appSettings> auswerten
        NameValueCollection col = ConfigurationManager.AppSettings;
        for (int i = 0; i < col.Count; i++) {
          Console.WriteLine("Name: {0} - Wert: {1}",
                             col.Keys[i], col[i]);
        }
        // <userSettings> einen neuen Wert zuordnen
        setting.Variable1 = "Hallo Peter!";
        setting.Save();
        // <appSettings> einen anderen Wert zuweisen
        col["Test"] = "Aachen";
        Console.WriteLine("Test (neu): {0}", col["Test"]);
        Console.ReadLine();
      }
    }
An diesem Code ist einiges erklärungsbedürftig. Betrachten Sie bitte zuerst die folgende Anweisung:
    Settings setting = new Settings();
Wenn es Sie interessiert, auf welcher Grundlage diese Anweisung basiert, öffnen Sie die Datei Settings.Designer.cs, die Sie innerhalb des Knotens Properties im Projektmappen-Explorer finden. Diese Datei wird automatisch von Visual Studio 2010 generiert. Sie enthält die Beschreibung der Klasse Settings, die von ApplicationSettingsBase abgeleitet ist. Settings ist ein Wrapper um die Anwendungskonfigurationsdatei und somit das Bindeglied zwischen den Konfigurationseinstellungen und dem Programmcode. Der Namespace, dem Settings zugeordnet ist, heißt AppConfigSample.Properties. Dieser Namespace ist mit using bekannt gegeben worden. In der Klasse werden alle Einstellungen aus der Anwendungskonfigurationsdatei als Eigenschaftsmethoden veröffentlicht. Die benutzerspezifischen Methoden haben folgerichtig einen get- und einen set-Zweig, die anwendungsspezifischen Methoden implementieren nur get und liefern deshalb nur den Wert zurück. Wenn wir Setting instanziieren, erhalten wir den Zugriff auf die Variablen, die in <applicationSettings> und <userSettings> definiert sind.
    string variable1 = setting.Variable1;
    string variable2 = setting.Variable2;
Schauen wir uns nun die beiden folgenden Anweisungen an:
    setting.Variable1 = "Hallo Peter!";
    setting.Save();
Variable1 gehört zu der Sektion <userSettings>. Während beim ersten Aufruf noch der Inhalt Andreas lautet, wird dieser nach der Konsolenausgabe geändert. Das bewirkt, dass die Zeichenfolge Hallo Andreas! in die Datei user.config geschrieben wird, die unter Dokumente und Einstellungen\<Benutzer>\Lokale Einstellungen\Anwendungsdaten\<Firma>\<Anwendung> zu finden ist. Der Inhalt lautet wie folgt:
    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <userSettings>
        <AppConfigSample.Properties.Settings>
          <setting name="Variable1" serializeAs="String">
            <value>Hallo Peter!</value>
          </setting>
        </AppConfigSample.Properties.Settings>
      </userSettings>
    </configuration>
Bei allen folgenden Aufrufen wird anschließend immer die benutzerbezogene Zeichenfolge angezeigt. Hinter Setting steckt noch ein kleines Geheimnis, denn es handelt sich um eine partielle Klasse. Vielleicht haben Sie das Beispiel von der Buch-DVD ausprobiert und mussten feststellen, dass an der Konsole die Ausgabe Der Wert für Variable1 wurde verändert angezeigt wird, ohne dass diese Ausgabe in Main codiert ist. Sehen Sie noch einmal Abbildung 15.14 an. In dem abgebildeten Dialog sehen Sie im oberen Bereich eine Schaltfläche Code anzeigen. Wenn Sie auf diese Schaltfläche klicken, öffnet sich ein Codeeditor mit der partiellen Klasse Settings und dem Codegerüst von zwei Ereignishandlern, die zu den beiden Ereignissen SettingsChanging und SettingsSaving gehören, die ein Settings-Objekt auslösen kann. Beide Ereignishandler sind noch nicht bei den Ereignissen registriert. Dazu müssen Sie nur die Auskommentierungen im Konstruktor aufheben:
    internal sealed partial class Settings {
      public Settings() {
        // this.SettingChanging += this.SettingChangingEventHandler;
        // this.SettingsSaving += this.SettingsSavingEventHandler;
      }
      private void SettingChangingEventHandler(object sender,
                                   SettingChangingEventArgs e)
      {
      }

      private void SettingsSavingEventHandler(object sender,
                                          CancelEventArgs e)
      {
      }
    }
Das SettingsSaving-Ereignis wird von der Save-Methode ausgelöst, bevor die Anwendungseinstellung gespeichert wird. Der zugeordnete Ereignishandler vom Typ CancelEventArgs kann den eingeleiteten Speichervorgang abbrechen. Das SettingChanging-Ereignis tritt ein, bevor eine Anwendungseinstellung über den Indexer geändert wird. Der zweite Parameter des Ereignishandlers ermöglicht das Abrufen der zu ändernden Einstellung sowie des zugewiesenen Werts und darüber hinaus auch den Abbruch der Operation. Und genau dieser Ereignishandler ist im Beispielprogramm programmiert und führt zu der im ersten Moment erstaunlichen Konsolenausgabe. #### Die Klassen »Configuration« und »ConfigurationManager« Mit
    NameValueCollection col = ConfigurationManager.AppSettings;
machen Sie nun ersten Mal Bekanntschaft mit der Klasse ConfigurationManager. Wenn wir diese Klasse betrachten, müssen wir gleichzeitig auch die Klasse Configuration besprechen. Beide gehören zum Namespace System.Configuration. Um die Klassen nutzen zu können, ist es erforderlich, einen Verweis auf System.Configuration zu legen. ConfigurationManager und Configuration dienen dazu, Konfigurationsdateien auszuwerten und zu ändern. Dass uns zwei Klassen angeboten werden, ist wohl historisch bedingt, denn Configuration wurde erst mit .NET 2.0 bereitgestellt, während ConfigurationManager schon in .NET 1.0 vertreten war. Die ConfigurationManager-Klasse ermöglicht es Ihnen, auf Maschinen- und Anwendungskonfigurationsinformationen zuzugreifen. Die beiden einzigen Eigenschaften, die ConfigurationManager veröffentlicht, lauten AppSettings und ConnectionStrings, über die der Zugriff auf die Abschnitte <appSettings>- und <connectionStrings> möglich wird.

Tabelle 15.2 Die Eigenschaften der Klasse »ConfigurationManager«

Eigenschaft | Beschreibung
AppSettings | Ruft die AppSettingsSection-Daten für die Standardkonfiguration ab.
ConnectionStrings | Ruft die ConnectionStringsSection-Daten für die Standardkonfiguration ab.
Nicht viel größer ist die Anzahl der Methoden. Die wichtigsten finden Sie in Tabelle 15.3.

Tabelle 15.3 Die Methoden der Klasse »ConfigurationManager«

Methode | Beschreibung
GetSection | Ruft einen angegebenen Konfigurationsabschnitt für die Standardkonfiguration ab.
OpenExeConfiguration | Öffnet die angegebene Clientkonfigurationsdatei als Configuration-Objekt.
OpenMachineConfiguration | Öffnet die Computerkonfigurationsdatei auf dem aktuellen Computer als Configuration-Objekt.
RefreshSection | Aktualisiert den benannten Abschnitt.
Configuration repräsentiert die Einstellungen einer Anwendung oder des Computers. Die Implementierung der Klasse berücksichtigt dabei, dass Anwendungen die Einstellungen in machine.config erben. Configuration ist konstruktorlos. Die Klasse ConfigurationManager stellt beim Aufruf entsprechender Methoden (OpenExeConfiguration und OpenMachineConfiguration) die Referenz auf das Configuration-Objekt zur Verfügung. Configuration gibt uns mit seinen Eigenschaften und Methoden alle Mittel an die Hand, um Sektionen bzw. Sektionsgruppen abzurufen, den physikalischen Pfad der Konfigurationsdatei abzurufen und Einstellungen zu speichern. In den Tabellen 15.4 und 15.5 sind die wichtigsten Eigenschaften und Methoden aufgeführt.

Tabelle 15.4 Die Eigenschaften eines »Configuration«-Objekts

Eigenschaft | Beschreibung
AppSettings | Ruft den Konfigurationsabschnitt des AppSettingsSection-Objekts ab.
ConnectionStrings | Ruft ein ConnectionStringsSection-Konfigurationsabschnittsobjekt ab.
FilePath | Ruft den physikalischen Pfad zu der Konfigurationsdatei ab.
Locations | Ruft die in diesem Configuration-Objekt definierten Speicherorte ab.
RootSectionGroup | Ruft die Stamm-ConfigurationSectionGroup ab.
SectionGroups | Ruft eine Auflistung der von dieser Konfiguration definierten Abschnittsgruppen ab.
Sections | Ruft eine Auflistung der von dieser Konfiguration definierten Abschnitte ab.

Tabelle 15.5 Die Methoden eines »Configuration«-Objekts

Methode | Beschreibung
GetSection | Gibt das angegebene ConfigurationSection-Objekt zurück.
GetSectionGroup | Ruft das angegebene ConfigurationSectionGroup-Objekt ab.
Save | Schreibt die Konfigurationseinstellungen in die aktuelle XML-Konfigurationsdatei.
SaveAs | Schreibt die Konfigurationseinstellungen in die angegebene XML-Konfigurationsdatei.
Wie Sie die Klassen Configuration und ConfigurationManager einsetzen können, zeige ich Ihnen im folgenden Abschnitt. ### 15.3.6 Editierbare, anwendungsbezogene Einträge mit <appSettings> Einträge, die Sie in der Anwendungskonfigurationsdatei im Abschnitt <applicationSettings> vornehmen, sind nicht editierbar – zumindest aus dem Code einer Anwendung heraus. Man kann die Werte jedoch jederzeit ändern, indem man die Datei mit einem beliebigen Editor öffnet. Das ist insofern sinnvoll, weil auf diese Weise nicht ein Benutzer von den Änderungen eines anderen Benutzers abhängig gemacht wird. Nichtsdestotrotz könnten Sie als Entwickler auch einmal in die Situation kommen, aus dem Code heraus eine anwendungsweite Einstellung ändern zu wollen oder eine neue hinzuzufügen. Das kann nur in der Sektion <appSettings> erfolgen. Das folgende Beispiel AppSettingsSample zeigt, wie Sie mit den Klassen Configuration und ConfigurationManager die Einstellungen in <appSettings> beeinflussen können.
    // ---------------------------------------------------------
    // Beispiel: ...\Kapitel 15\AppSettingsSample
    // ---------------------------------------------------------
    class Program {
      static void Main(string[] args) {
        Console.WriteLine("Ursprüngliche 'appSettings'-Einstellungen:");
        ShowAppSettings();
        Console.WriteLine("\nHinzufügen eines Eintrags:");
        // Bezeichner des Eintrags festlegen
        string entry = "Nummer" + ConfigurationManager.AppSettings.Count;
        // 'appSettings'-Eintrag hinzufügen
        Configuration config = ConfigurationManager.
           OpenExeConfiguration(ConfigurationUserLevel.None);
        config.AppSettings.Settings.Add(entry,
                               DateTime.Now.ToLongTimeString());
        // Ändern des ersten Eintrags
        if (config.AppSettings.Settings.Count > 2)
          config.AppSettings.Settings["Nummer" +
            (config.AppSettings.Settings.Count - 3)].Value = "veraltet";
        // Speichern aller Änderungen
        config.Save(ConfigurationSaveMode.Modified);
        // Erneutes Auslesen der Sektion 'appSettings'
        ConfigurationManager.RefreshSection("appSettings");
        Console.WriteLine("\nGeänderte 'appSettings'-Einstellungen:");
        ShowAppSettings();
        // Anzeige des letzten Eintrags in der Konfigurationsdatei
        Console.WriteLine("\nDer letzte Eintrag ist {0}",
                   ConfigurationManager.AppSettings[entry]);
        Console.ReadLine();
      }
      static void ShowAppSettings() {
        string[] names = ConfigurationManager.AppSettings.AllKeys;
        NameValueCollection appStgs = ConfigurationManager.AppSettings;
        for (int i = 0; i < appStgs.Count; i++) {
          Console.WriteLine("Nr.{0} - Wert: {1}", i, appStgs[i]);
      }
    }
Wenn Sie die Anwendung testen wollen, dürfen Sie sie nicht aus der Entwicklungsumgebung heraus starten, sondern müssen das Kompilat starten. Ansonsten werden Sie den Effekt nicht sehen können, weil die Datei App.config permanent neu geschrieben wird. Abbildung 15.15 zeigt die Ausgabe der Anwendung. Hier klicken, um das Bild zu vergrößern Abbildung 15.15 Die Ausgabe des Beispiels »AppSettingsSample« Bei jedem Neustart wird ein zusätzlicher Eintrag in die Anwendungskonfigurationsdatei geschrieben. Es handelt sich hierbei um die aktuelle Uhrzeit. Allerdings sollen nur die beiden letzten Starts auf diese Weise protokolliert werden, alle anderen Einträge werden mit »veraltet« überschrieben. Für die Ausgabe des aktuellen Inhalts sorgt die Methode ShowAppSettings, in der zuerst alle namentlichen Einträge mit
    string[] names = ConfigurationManager.AppSettings.AllKeys;
abgefragt werden. ConfigurationManager.AppSettings liefert uns die Referenz auf ein Objekt vom Typ NameValueCollection. In diesem sind alle Elemente mit einem eindeutigen Schlüssel, einer Zeichenfolge, eingetragen. Alle Schlüssel werden als Array von der Eigenschaft AllKeys bereitgestellt. In einer Schleife werden alle Schlüssel abgegriffen und die zugeordneten Werte an der Konsole ausgegeben. Als Collection stellt eine NameValueCollection passende Methoden bereit, um die Einträge zu manipulieren. Wir benutzen die Methode Add, um einen Neueintrag hinzuzufügen, und übergeben als Argumente den zuvor gebildeten neuen Elementnamen und anschließend die aktuelle Uhrzeit.
    config.AppSettings.Settings.Add(entry, DateTime.Now.ToLongTimeString());
Da wir beabsichtigen, den Neueintrag auch zu speichern, benötigen wir ein Configuration-Objekt. Mit
    Configuration config =
    ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
holen wir uns die Referenz auf das benötigte Objekt, das die Anwendungskonfigurationsdatei verkörpert. Für das Speichern steht uns mit Save die passende, überladene Methode zur Verfügung.
    config.Save(ConfigurationSaveMode.Modified);