Konfigurationssystem

Dieses Kapitel beschreibt alle Elemente unseres Konfigurationssystems. Die hier verwendeten Illustrationen zeigen möglicherweise andere Anwendungen. Das Konfigurationssystems ist jedoch identisch und verhält sich für all unsere Produkte gleich.

Das Konfigurationssystem ist integraler Teil der meisten unsere Produkte. Es sorgt dafür das du eine Anwendung mit einer oder mehreren klar definierten XMl Dateien konfigurieren kannst. Zudem bietet es eine unglaubliche Flexibilität mit Platzhaltern und verschiedenen Optionen wo die Konfiguration platziert werden kann.

Features

  • XML basierendes Format: Die Konfiguration besteht aus einer definierten XML Datei zu welcher auch ein Schema existiert. So kannst du die Konfiguration sowohl mit einem einfachen Texteditor oder spezialisierten Tools bearbeiten.

  • Codierte Passwörter: Mit unserem integrierten Password Encoder Tool kannst du Passwörter in der Konfiguration unkenntlich machen. So können diese nur mit grösserem Aufwand kopiert werden.

  • Module: Die Konfiguration grosser Produkte ist in Module aufgeteilt, so kannst du die Konfiguration einfach auf mehrere Dateien verteilen.

  • Platzhalter: Mit Platzhaltern kannst du Pfade, Daten und andere Elemente in die Konfiguration einfügen.

Dateien und Orte für die Konfiguration

Es existiert ein default Verhalten wie das System nach Konfigurationsdateien sucht. Dieses Verhalten kann jedoch individuell durch jede Anwendung verändert werden. In diesem Fall findest du einen entsprechenden Hinweis in der Dokumentation der Anwendung.

Die Suchpfade

Das System durchsucht die folgenden Verzeichnisse in der angegeben Reihenfolge nach Konfigurationsdateien:

  • Betriebssystem App Konfiguration/EducateIT/Produktname

  • App Verzeichnis

Der Teil Betriebssystem App Konfiguration hängt vom verwendeten Betriebssystem und dessen Version ab. Du findest du verschiedenen Werte in der folgenden Tabelle:

OS

Version

Pfad

Mac

10.*
11.*

/Library/Application Support/EducateIT/Produktname

Linux

Alle

Hier hängt der Suchpfad davon ab, wo die Anwendung installiert wurde. Falls sie in /bin, oder /usr/bin installiert ist, wird :file:‘/etc` oder /usr/etc durchsucht. Falls die in /opt/bin installiert ist, wird nur /opt/etc/ durchsucht. Falls sie in /usr/local/bin installiert ist, wird nur /usr/local/etc/ durchsucht.
/usr/local/etc/EducateIT/Produktname
/opt/etc/EducateIT/Produktname
/usr/etc/EducateIT/Produktname
/etc/EducateIT/Produktname

Windows

97
XP
2000
C:/Documents and Settings/All Users/Application Data/EducateIT/Produktname
%ALLUSERSPROFILE%/Application Data/EducateIT/Produktname

Windows

7
8
10+
C:/ProgramData/EducateIT/Produktname
%SystemDrive%/ProgramData/EducateIT/Produktname

Der Produktname

Der Produktname welcher in den Pfaden oben angegeben wird entspricht exakt dem Namen der im Titel der Anwendung angegebenen wird. Alternativ oder bei Kommandozeilentools kannst du den Namen mit der --version Option abfragen. Der Produktname muss inklusive aller darin enthaltenen Zahlen und Leerzeichen angegeben werden.

Beispiel: Ist der Produktname Example Application und läuft auf einem Computer mit Windows 10, dann werden die folgenden Verzeichnisse durchsucht.

  • C:/ProgramData/EducateIT/Example Application/

  • C:/Program Files/EducateIT/Example Application/

Dateinamen der Konfiguration

Eine Konfigurationsdatei hat standardmässig den folgenden Namen:

configuration.xml

Wenn also in einem der durchsuchten Verzeichnissen eine solche Datei gefunden wird, geht das System davon aus, dass es sich dabei um die Konfiguration der Anwendung handelt.

Daneben können beliebig viele Dateien mit der Endung *.conf_b.xml existieren. Wird in einem der durchsuchten Verzeichnisse eine Datei mit dieser Endung gefunden, dann wird Sie zu der Liste der Konfigurationsdateien hinzugefügt. Die folgende Liste zeigt einige gültige Dateinamen für Konfigurationsdateien:

Application.conf_b.xml
part1.conf_b.xml
module core.conf_b.xml

Alle gefundenen Konfigurationsdateien werden gelesen und interpretiert. Danach fasst das Konfigurationssystem die Werte aus allen gelesenen Konfigurationen zusammen und überprüft ob diese gültig sind.

Die Struktur einer Konfigurationsdatei

Jede Konfigurationsdatei ist ein gültiges XML Dokument. Als Zeichenkodierung empfehlen wir UTF-8.

Das folgende Beispiel zeigt die grundlegende Struktur einer Konfigurationsdatei mit dem Dokument-Tag und den korrekten Bezeichner für das Konfigurationsschema:

XML Struktur einer Konfigurationsdatei
<?xml version="1.0" encoding="UTF-8" ?>
<Configuration
    version="1"
    xmlns="http://educateit.ch/software/BlueStone/Configuration/1">
...
</Configuration>
Attribut version:

Der Wert dieses Attributs muss immer auf 1 gesetzt sein, es ermöglicht spätere Erweiterungen des Konfigurationsformats.

Attribut xmlns:

Mit der URI welche in diesem Attribut angegeben ist wird das XML Schema der Konfigurationsdatei definiert. Siehe auch Schema der Konfigurationsdateien.

Die folgende Illustration zeigt die Struktur einer Konfigurationsdatei und die Relationen zwischen den XML Elementen:

../../../_images/configuration-file-structure.jpg

Die Struktur einer Konfigurationsdatei

Beim blauen Block <Configuration> handelt es sich um das Dokument-Tag, wie es im Listing XML Struktur einer Konfigurationsdatei gezeigt wird. Die Linie mit dem Pfeil welche von diesem Block ausgeht, zeigt welche Elemente in diesem enthalten sein können. In diesem Fall sind es die Elemente Module, IncludeFile, IncludeDirectory und SearchDirectory.

Die kleinen schwarzen Zahlen an den Pfeillinien zeigen, wie viele der Blöcke vorkommen dürfen. Dabei bedeutet 0..n von keinem bis beliebig viele Elemente und 0..1 bedeutet keines oder ein einzelnes Element.

Die folgenden Kapitel beschreiben jetzt jedes Element und dessen Bedeutung.

Das Configuration Element

Das Configuration Element bildet die basis jeder Konfigurationsdatei. Das wichtigste Unterelement ist hier das Module Element, welches die eigentlichen Konfigurationswerte für die Anwendung enthält.

Daneben lassen sich mit dem IncludeFile und IncludeDirectory Element zusätzliche Konfigurationsdateien einbinden.

Der Aufbau eines Konfigurationsdokuments mit zwei Modulen, welches eine zusätzliche Konfigurationsdatei einbindet, könnte folgendermassen aussehen:

Beispiel einer Konfigurationsdatei mit zwei Modulen
<Configuration>

    <Module name="Application">
        ...
    </Module>

    <Module name="LogSystem">
        ...
    </Module>

    <IncludeFile>X:/Example/example.xml</IncludeFile>

</Configuration>

Bemerkung

Für die Lesbarkeit lassen wir in den Beispielen viele Dinge weg: Die drei Punkte (...) markieren Stellen, an denen wir Elemente weggelassen haben. Auch fehlen im Configuration Element die wichtigen Attribute für die Version und das XML Schema. Für eine Gültige Datei, muss das Dokument Element aussehen wie in Listing XML Struktur einer Konfigurationsdatei.

Dies ist eine Konvention, welche du auch in unseren anderen Dokumentation findest, ohne dass diese explizit erklärt wird. Betrachte Listings in der Dokumentation daher immer als Beispiele und kopiere diese nicht unverändert in eine Datei.

Das IncludeFile Element

Mit dem IncludeFile Element bindest du eine zusätzliche Konfigurationsdatei ein. Als Inhalt wird ein relativer oder absoluter Pfad zu der Konfigurationsdatei erwartet. Wenn du einen relativen Pfad verwendest, dann wird die Datei in allen Suchpfaden des Konfigurationssystems gesucht.

Die referenzierte Datei muss eine gültige Konfigurationsdatei sein, wie sie hier beschrieben wird. Die Datei kann wiederum alle Möglichkeiten welche das Konfigurationssystem bietet ausnutzen. Du kannst sogar die Definition eines Module Elements auf zwei Dateien aufteilen, dabei musst du lediglich sicherstellen das jeder Wert nur einmal in der Gesamtkonfiguration vorkommt.

Es existiert auch eine Kommandozeilenoption --config-file mit der du zusätzliche Konfigurationsdateien hinzufügen kannst. Siehe dazu Hinzufügen einer Konfigurationsdatei.

Das IncludeDirectory Element

Mit dem IncludeDirectory Element bindest du zusätzliche Verzeichnissen in die Konfiguration ein. Als Inhalt des Elements wird ein relativer oder absoluter Pfad zu einem Verzeichnis erwartet. Wenn du einen relativen Pfad verwendest, dann wird dieser immer relativ zu dem Verzeichnis interpretiert, aus welchem die aktuelle Konfiguration gerade gelesen wird.

Das angegebene Verzeichnis wird nach Konfigurationsdateien durchsucht. Es werden dabei nur Dateien berücksichtigt, welche die Dateiendung .conf_b.xml haben.

Die folgende Illustration zeigt die Funktionsweise dieses Elements anhand von einem Beispiel. Alle Konfigurationsdateien mit der passenden Dateiendung werden dabei gelesen.

../../../_images/directory-include.jpg

Es existiert auch eine Kommandozeilenoption --config-dir mit der du zusätzliche Verzeichnisse hinzufügen kannst. Siehe dazu Hinzufügen eines Konfigurationsverzeichnisses.

Das SearchDirectory Element

Mit dem SearchDirectory Element fügst du einen weiteren Suchpfad zum Konfigurationssystem hinzu. Relative Pfade, welche du in nachfolgende IncludeFile Elementen angibst, werden in allen regulären und diesen zusätzlichen Verzeichnissen gesucht.

Du kannst für dieses Element einen absoluten oder einen relativen Pfad verwenden. Verwendest du einen relative Pfad, wird dieser ausgehend von dem Verzeichnis der aktuellen Konfigurationsdatei aufgebaut.

Die Reihenfolge in der die Dateien gelesen werden

Für eine Korrekte Konfiguration sollte es keine Rolle spielen in welcher Reihenfolge die Dateien gelesen werden. Daher liest das Konfigurationssystem die Dateien in der Reihenfolge ein, in welcher diese Definiert werden. Eine Überprüfung aller Werte wird erst durchgeführt, nachdem alle Dateien gelesen und interpretiert wurden.

Suchpfade welche du mit dem SearchDirectory Element hinzufügst, werden immer vor allen IncludeFile Elementen in der selben Datei bearbeitet. Es spielt also keine Rolle in welcher Reihenfolge du die Suchpfade angibst.

Das Module Element

Das Module Element ist das wichtigste Element der Konfiguration. Es enthält die eigentlichen Werte der Konfiguration. Schau dir dazu nochmals die Illustration Die Struktur einer Konfigurationsdatei an.

Jeder Modul block innerhalb der Konfiguration bezieht sich auf einen bestimmten Teil der Applikation. Dieser Teil wird mit einem Namen über das Attribut name angegeben. Einfache Anwendungen haben meistens nur das Modul Application, aber komplexere Anwendungen mit Erweiterungen können viele verschiedene Module definieren, welche über bestimmte Namen angesprochen werden. Die genauen Details dazu findest du im Konfigurationskapitel der Dokumentation zu der Applikation.

Unsere Applikation enthalten oft auch eingebettete Systeme, wie das Log-System oder das Service-System. Diese definieren auch optionale Module, welche du in der Konfiguration definieren kannst. Ob solche Systeme in einer Anwendung enthalten sind wird in der jeweiligen Dokumentation der Applikation beschrieben. Du findest dann auch ein entsprechendes Kapitel im Inhaltsverzeichnis.

Innerhalb des Module Elements können beliebig viele Value, Group und List Elemente vorkommen.

Das folgende Beispiel zeigt wie die definition eines Module Elements aussehen kann:

Ein Modul Block mit einer Beispielkonfiguration
<Module name="Application">

    <Value name="path">●thisDirectory●</Value>

    <Group name="log">
        <Value name="target">c:\log\application.log</Value>
        <Value name="format">PlainText</Value>
    </Group>

    <List name="groups">
        <ListEntry>
            <Value name="id">group1</Value>
            <Value name="title">The First Group</Value>
        </ListEntry>
        <ListEntry>
            <Value name="id">group2</Value>
            <Value name="title">The Second Group</Value>
        </ListEntry>
    </List>

    <List name="files">
        <Value>file1.txt</Value>
        <Value>file2.txt</Value>
        <Value>file3.txt</Value>
        <Value>file4.txt</Value>
    </List>

</Module>

Das Value Element

Das Value Element enthält die eigentlichen Konfigurationswerte. Der Wert wird dabei durch das Element eingeschlossen. Im folgenden Beispiel siehst du den Konfigurationswert path, der als c:/config/serverlist.json definiert wird:

<Value name="path">c:/config/serverlist.json</Value>

Es spielt dabei keine Rolle, ob du vor und nach dem eigentlichen Wert noch Leerzeichen oder Zeilenumbrüche einfügst. Das folgenden Beispiel ist identisch zu dem letzten Beispiel:

<Value name="path">
    c:/config/serverlist.json
</Value>

Je nach definition, muss der angegebene Wert einem bestimmten Typ entsprechen. Ist dieser Typ Beispielsweise eine Ganzzahl (integer), dann darfst du nur ganze Zahlen angeben, ansonsten ist die Konfiguration ungültig.

Das Attribut name

In den meisten Fällen musst du beim Value Element das Attribut name angeben. Innerhalb eines Module, Group oder ListEntry Elements kannst du beliebig viele Value Elemente definieren. Mit dem name Attribut definierst du um welchen Wert es sich bei deiner Definition handelt.

Das folgende Beispiel Zeigt ein Module Element das drei verschiedene Werte enthält. Mit dem name Attribut werden die Werte path, order und maximumSize definiert.

<Module name="Application">
    <Value name="path">c:/test/</Value>
    <Value name="order">descending</Value>
    <Value name="maximumSize">100k</Value>
</Module>

Die einzige Ausnahme sind die einfachen Listen (siehe Einfache Listen), hier gibst du eine Liste von Werten an. Da es sich bei der Liste um einen einzigen Konfigurationswert handelt lässt du das name Attribut weg.

<List name="files">
    <Value>file1.txt</Value>
    <Value>file2.txt</Value>
    <Value>file3.txt</Value>
    <Value>file4.txt</Value>
</List>

Das Attribut placeholder

Jedes Value Element kann das optionale Attribut placeholder enthalten. Mit diesem Attribut steuerst du, ob im Text des Konfigurationswertes Platzhalter ersetzt werden oder nicht. Du kannst dabei dem Attribut zwei verschiedene Bezeichner zuweisen:

  • Replace: Platzhalter werden ersetzt. Dies ist der Default.

  • Ignore: Platzhalter werden ignoriert.

Schau dir dazu folgendes Beispiel an:

<Value>●computerName●<Value>                        EXAMPLE
<Value placeholder="Replace">●computerName●<Value>  EXAMPLE
<Value placeholder="Ignore">●computerName●<Value>   ●computerName●

Die verschiedenen Typen innerhalb des Value Elements

In der Beschreibung einer Konfiguration siehst du verschiedene Typen welche den Werten zugeordnet werden. Diese Typen definieren was du bei einem Konfigurationswert angeben darfst.

Text (string)

Text kann jede beliebige Form von Text sein. Von einfachen Schlüsselwörtern bis zu langen mehrzeiligen Texten. Beachte jedoch, dass du XML-Spezialzeichen wie &, < und > als &amp;, &lt; und &gt; schreiben musst, ansonsten wird das XML Dokument möglicherweise ungültig. Alternativ kannst du längeren Text auch in <![CDATA[ und ]]> einschliessen. Innerhalb dieser „Klammern“ kannst du die Spezialzeichen verwenden, ohne das du die spezielle escape Syntax verwenden musst.

Das folgende Beispiel zeigt zwei einfache Konfigurationswerte mit Text:

<Value name="firstValue">Example</Value>
<Value name="secondValue">A longer example text</Value>

Falls du Skripte oder XML Dokumente in der Konfiguration einbettest, solltest du in jedem Fall den Text mit <![CDATA[ und ]]> einschliessen. Das folgende Beispiel zeigt ein Wert der XML Fragmente enthält und ein Wert mit einem Skript.

<Value name="htmlCode"><![CDATA[
    <p>Some formatted <i>HTML</i> code.</p>
]]></Value>
<Value name="script"><![CDATA[
    if (x > 27 && y < 12) {
        result = "Success!";
    }
]]></Value>

Eine Konfigurationsdefinition kann den Text mit Regeln weiter einschränken. Die folgende Liste zeigt dir einige Beispiele für mögliche Einschränkungen:

  • Minimale oder maximale Länge

  • Auswahl von möglichen Bezeichnern

  • Regulärer Ausdruck

  • Gültiger und/oder existierender Datei- oder Verzeichnispfad

Passwörter (password)

Der Passwort-Typ ist ein Spezialfall von Text der auf Passwörter spezialisiert ist. Alles was beim Text beschrieben wird ist auch für den Passwort-Typ gültig.

Werte von diesem Typ werden niemals in eine Logdatei geschrieben und werden im Speicher speziell geschützt. Zudem lassen sich die Passwörter kodieren, damit Sie schwieriger extrahiert werden können.

Textlisten (string list)

Textlisten definieren eine Liste von Bezeichnern, welche durch Whitespace [1] getrennt wird. Das folgende Beispiel zeigt eine Liste von drei verschiedenen Bezeichnern:

<Value name="a">apple orange banana</Value>

Da Whitespace-Zeichen ignoriert werden, kann die Liste auch anders formatiert werden:

<Value name="a">
    apple
    orange
    banana
</Value>

Ganzzahlen (integer)

Ganzzahlwerte können positive oder negative Zahlen ohne Nachkommastellen sein. Die Anwendung kann zudem den Bereich der Zahlen weiter einschränken. Das folgende Beispiel zeigt zwei Konfigurationswerte mit Ganzzahlen:

<Value name="a">-12</Value>
<Value name="b">7000</Value>

Werten dieses Typs kannst du zudem im Hexadezimalsystem angeben, indem du die Zahl mit einem 0x Präfix versiehst. Das folgende Beispiel zeigt zwei Werte im Hexadezimalsystem:

<Value name="a">0xE</Value>
<Value name="b">0x01b9</Value>

Damit du einfacher Datenmengen konfigurieren kannst, sind auch die übliche Suffixe wie kb, mb und gb möglich. Sie multiplizieren die Zahl um 1000, 1000² und 1000³. Das folgende Beispiel zeigt einige Werte mit diesen Suffixen:

<Value name="a">128kb</Value>
<Value name="b">20 mb</Value>
<Value name="c">177 GB</Value>
<Value name="d">12.9 GB</Value>
<Value name="e">0.5 tb</Value>

Möglich ist auch die alternative binäre Zählweise, welche auf dem Faktor 1024 basiert. Diese Suffixe werden als KiB, MiB und GiB geschrieben. Das folgende Beispiel zeigt einige dieser Werte:

<Value name="a">128kib</Value>
<Value name="b">20 MiB</Value>
<Value name="c">177 GiB</Value>

Wenn du ein solches Suffix verwendest, kannst du auch Werte wie 0.5 kb angeben, welches 500 bytes entspricht. Solche Werte werden immer auf die nächste Ganzzahl gerundet.

Mögliche Suffixe findest du in der folgenden Tabelle. Die Gross-/Kleinschreibung spielt bei den Suffixen keine Rolle.

Suffix

Faktor

Suffix

Faktor

ohne

1

Byte

1

KB

1000

KiB

1024

MB

1000²

MiB

1024²

GB

1000³

GiB

1024³

TB

10004

TiB

10244

PB

10005

PiB

10245

EB

10006

EiB

10246

ZB [2]

10007

ZiB [2]

10247

YB [2]

10008

YiB [2]

10248

Boolescher Wert (boolean)

Ein boolescher Wert kann nur wahr oder falsch sein. Du kannst diese beiden Zustände mit den Bezeichnern True und False`, sowie ``Yes und No angeben. Die Gross/-Kleinschreibung wird dabei nicht unterschieden.

Das folgende Beispiel zeigt einige Konfigurationswerte mit dem booleschen Typ:

<Value name="a">false</Value>
<Value name="b">TRUE</Value>
<Value name="c">No</Value>
<Value name="d">yes</Value>

Das Group Element

Das Group Element wird nicht sehr oft in Konfigurationen verwendet. Es dient dazu, eine Gruppe von Werten mit einem Bestimmten Namen zusammenzufassen. Das macht Beispielsweise sinn, um die Namen zu vereinfachen oder falls bestimmte Werte als Gruppe optional sind und nur zusammen weggelassen werden können.

Eine solche Gruppe entspricht dem Module Element und kann beliebig viele Value, Group und List Elemente enthalten.

Das folgende Beispiel zeigt eine Gruppe von Werten:

<Group name="a">
    <Value name="a">value1</Value>
    <Value name="b">value2</Value>
</Group>

Das List Element

Mit dem List Element werden einfache oder auch komplexe Listen definiert. Die einfache Liste definiert dabei eine Liste von Werten eines bestimmten Typs, wogegen die komplexe Liste eine Liste von mehreren verschiedenen Werten definiert.

Komplexe Listen

In der komplexen Liste ist jeder Eintrag ein ListEntry Element. Dieses Element kann dann beliebig viele Value, Group und sogar weitere List Elemente enthalten. Die Struktur jedes ListEntry Elements ist dabei gleich.

Das folgende Beispiel zeigt eine solche Liste mit drei Einträgen. Du siehst in dem Beispiel, wie die Definition in jedem ListEntry Element mit anderen Werten wiederholt wird.

<List name="x">
    <ListEntry>
        <Value name="a">12</Value>
        <Value name="b">test entry 1</Value>
    </ListEntry>
    <ListEntry>
        <Value name="a">20</Value>
        <Value name="b">test entry 2</Value>
    </ListEntry>
    <ListEntry>
        <Value name="a">92</Value>
        <Value name="b">test entry 3</Value>
    </ListEntry>
</List>

Die Reihenfolge der Einträge in einer solchen Liste ist Teil der Konfiguration und kann in bestimmten Anwendungen eine Rolle spielen. Beispielsweise kann die Liste von Filtern in der definierten Reihenfolge getestet werden.

Einfache Listen

In einer einfachen Liste wird nur ein einzelner Wert für jeden Eintrag definiert. Sie wird aus einzelnen Value Elemente zusammengesetzt. Dabei hat in diesem Fall das Value Element kein name Attribut.

Das folgende Beispiel zeigt eine einfache Liste mit fünf Einträgen:

<List name="x">
    <Value>list entry A</Value>
    <Value>list entry B</Value>
    <Value>list entry C</Value>
    <Value>list entry D</Value>
    <Value>list entry E</Value>
</List>

Auch bei der einfachen Liste kann je nach Anwendung die reihenfolge der Einträge eine Rolle spielen.

Platzhalter

Mit Platzhaltern kannst du verschiedene Systemwerte in den Text der Konfiguration einfügen. Diese Platzhalter werden noch vor der Überprüfung der Konfiguration ersetzt.

Platzhalter sind unabhängig von jeder Anwendung, daher kannst du sie in jeder Konfiguration verwenden. Teilweise verwenden unsere Anwendungen eigene Platzhalter-Systeme mit einer anderen Syntax. Wichtig für dich: Die Platzhalter des Konfigurationssystems werden immer zuerst ersetzt, bevor die Anwendung die Werte sieht.

Aufbau eines Platzhalters

Jeder Platzhalter wird mit zwei „●“ („black circle“, 0x25cf) Unicode Zeichen eingeschlossen. Dieses Zeichen wird verwendet, da es selten in normalen Text vorkommen und so selten Konflikte mit regulärem Text entstehen. Zudem kommt das Zeichen in den meisten Schriftarten vor, und kann so mit den meisten Texteditoren verwendet werden.

Es existieren zwei Formen für Platzhalter in der Konfiguration:

●name●
●name(parameter)●

Die erste Form besteht nur aus einem Namen; die zweite Form hat zusätzlich weitere Parameter welche mit runden Klammern hinter dem Namen stehen. Die Gross-/Kleinschreibung wird beim Namen immer unterschieden.

Anwendungsverzeichnis Platzhalter

Mit dem Platzhalter für das Anwendungsverzeichnis fügst du dieses in die Konfiguration ein.

●applicationDirectory●

Dabei handelt es sich um das Verzeichnis, aus welchem die Anwendung gestartet wird. Startest du also eine Anwendung mit dem Pfad „A“, dann ist das Anwendungsverzeichnis der Pfad „B“:

A: c:/Program Files/EducateIT/Process Monitor/ProcessMonitor.exe
B: c:/Program Files/EducateIT/Process Monitor

Das Verzeichnis ended niemals mit einem Pfadtrennzeichen. Falls du mit dem Platzhalter Dateien oder Verzeichnisse innerhalb des Anwendungsverzeichnis ansprechen möchtest, musst darfst du diesen nicht weglassen:

<Value name="path">●applicationDirectory●/subdir/example.txt</Value>

Aktuelles Verzeichnis Platzhalter

Dieser Platzhalter wird immer mit dem Verzeichnis ersetzt, in welchem sich die aktuell gelesene Konfigurationsdatei befindet. Der Platzhalter sieht wie folgt aus:

●thisDirectory●

Falls die Konfigurationsdatei den Pfad „A“ hat, dann entspricht der Platzhalter Pfad „B“ im folgenden Beispiel:

A: x:/configuration/assistant_config.conf_b.xml
B: x:/configuration

Das Verzeichnis ended niemals mit einem Pfadtrennzeichen. Falls du mit dem Platzhalter Dateien oder Verzeichnisse innerhalb des Anwendungsverzeichnis ansprechen möchtest, musst darfst du diesen nicht weglassen:

<IncludeFile>●thisDirectory●/additional_configuration.conf_b.xml</IncludeFile>

Datum/Zeit Platzhalter

Mit diesem Platzhalter fügst du ein Datum und/oder eine Uhrzeit in die Konfiguration ein. Dabei kannst du das Format steuern und auch ein Offset zu der aktuellen Zeit angeben. Als Basis wird immer die Zeit des Starts der Anwendung verwendet.

In der ersten Form des Platzhalters gibst du das Datums-/Zeitformat hinter dem Platzhalter mit zwei Apostroph-Zeichen (Unicode 0x0027) an. Die in dem Format verwendeten Zeichenkombinationen sind in dem Kapitel Datum/Zeit Format beschrieben.

●datetime('<format>')●

In der zweiten Form folgt nach dem Format, getrennt mit einem Komma das Offset.

●datetime('<format>',<offset>)●

Das Offset besteht dabei aus einer positiven oder negativen Ganzzahl, gefolgt von einem einzelnen Zeichen das die Einheit dieser Zahl angibt. Die möglichen Einheiten findest du in der folgenden Tabelle:

Zeichen

Bedeutung

y

Jahre

m

Monate

d

Tage

s

Sekunden

Die folgenden Beispiele zeigen einige gültige Datum/Zeit Platzhalter:

●datetime('yyyyMMdd')●      ⟹ Beispielsweise: 20210129
●datetime('yyyy')●          ⟹ Beispielsweise: 2021
●datetime('yyyyMMdd',-12d)● ⟹ Aktuelles Datum minus 12 Tage.
●datetime('yyyy',1y)●       ⟹ Aktuelles Jahr plus Eins.

Datum/Zeit Format

In der folgenden Tabelle findest du alle Textausdrücke und deren Bedeutung im Datumsformat. Alle anderen Zeichen werden genau so in das Resultat übernommen. Du kannst Text in Anführungszeichen einschliessen damit er nicht als Textausdruck interpretiert wird.

Ausdruck

Bedeutung

d

Der Tag als Zahl ohne führende Null (1-31).

dd

Der Tag als Zahl mit führendem Null (01-31).

ddd

Der abgekürzte übersetzte Tagesname (Beispielsweise „Mon“ bis „Sun“).

dddd

Der übersetzte Tagesname (Beispielsweise „Monday“ bis „Sunday“).

M

Der Monat als Zahl ohne führende Null (1-12).

MM

Der Monat als Zahl mit führender Null (01-12).

MMM

Der abgekürzte übersetzte Monatsname (Beispielsweise „Jan“ bis „Dec“).

MMMM

Der übersetzte Monatsname (Beispielsweise „January“ bis „December“).

yy

Das Jahr mit zwei Ziffern (00-99).

yyyy

Das Jahr mit vier Ziffern (0000-9999).

h

Die Stunde ohne führende Null (0-23 oder 1-12 bei der AM/PM Anzeige).

hh

Die Stunde mit einer führenden Null (00-23 oder 01-12 bei der AM/PM Anzeige).

H

Die Stunden ohne führende Null (0-23, auch bei der AM/PM Anzeige).

HH

Die Stunde mit einer führenden Null (00-23, auch bei der AM/PM Anzeige).

m

Die Minute ohne führende Null (0-59).

mm

Die Minute mit führender Null (00-59).

s

Die Sekunde ohne führende Null (0-59).

ss

Die Sekunde mit führender Null (00-59).

z

Die anzahl Millisekunden ohne führende Nulls (0-999).

zzz

Die anzahl Millisekunden mit führenden Nulls (000-999).

AP oder A

Die AM/PM Anzeige mit Grossbuchstaben, stellt das Format von h und hh um.

ap oder a

Die am/pm Anzeige mit Kleinbuchstaben, stellt das Format von h und hh um.

Computer- und Domainnamen

Mit den folgenden zwei Platzhaltern kannst du den Computer- respektive Domainnamen einfügen:

●computerName●
●domainName●

Umgebungsvariablen

Mit den folgenden Platzhaltern kannst du den Inhalt von Umgebungsvariablen in die Konfiguration einfügen. Dabei wird der Zustand der Umgebungsvariablen von dem Prozess welcher die Konfiguration liest verwendet.

●environmentVariable(temp)●
●environmentVariable(homedrive)●

Die Gross-/Kleinschreibung der angegeben Umgebungsvariablen spielt keine Rolle. Falls die angegebene Umgebungsvariable nicht existiert wird der Platzhalter mit einem leeren Text ersetzt.

Verschiedene Umgebungsvariablen werden aus Sicherheitsgründen gefiltert und können nicht verwendet werden. Selbst definierte Umgebungsvariablen sind jedoch von dieser Einschränkung nicht betroffen.

Angemeldeter Benutzer

Die folgenden Platzhalter funktionieren nur auf Windows-Systemen. Sie werden durch den angemeldeten Benutzer und der Domäne des angemeldeten Benutzers ersetzt.

●userName●
●userDomain●

Dabei wird immer der Benutzer verwendet der die Anwendung ausführt.

Optionen der Kommandozeile

Alle unsere Produkte welche dieses Konfigurationssystem verwenden akzeptieren auch Kommandozeilenoptionen. Dabei wird zwischen den langen und kurzen Optionen unterschieden, welche ein unterschiedliches Format haben. Anwendungen welche Kommandozeilenoptionen verwenden, bieten für häufig verwendete Optionen sowohl die kurze wie auch lange Schreibweise an. Selten verwendete Optionen werden nur in der langen Schreibweise angeboten.

Lange Optionen

Die langen Optionen starten immer mit zwei Bindestrichen (--), gefolgt von dem Namen der Option. Bei dem Namen wird die Gross-/Kleinschreibung unterschieden.

Das folgende Beispiel zeigt den Aufruf einer fiktiven Anwendung mit langen Kommandozeilenoptionen. Alle Optionen in dem gezeigten Beispiel sind sogenannte Flags, da sie keinen Wert definieren.

Application.exe --example-arg
Application.exe --arg1 --arg2 --arg3

In dem nächsten Beispiel siehst du den Aufruf einer fiktiven Anwendung mit langen Kommandozeilenoptionen welche zudem Werte definieren.

Application.exe --example=Simple
Application.exe --maximum=12402
Application.exe --another="Value with Spaces"
Application.exe "--another=Value with Spaces"
Application.exe --arg1=100 --arg2=200

Zwischen dem Namen der Option, dem Gleichzeichen und dem Wert dürfen keine Leerzeichen stehen. Falls der Wert Leerzeichen enthalten soll, musst du den Wert oder die ganze Option in Anführungszeichen einschliessen.

Kurze Optionen

Für häufig verwendete Optionen gibt es oft zusätzlich noch eine kurze Schreibweise. Eine kurze Option startet immer mit einem einzelnen Bindestrich (-), gefolgt von einem einzelnen Buchstaben. Die Gross-/Kleinschreibung dieses Buchstabens wird dabei unterschieden. Es macht daher einen Unterschied, ob du die Option -a oder -A verwendest.

Das folgende Beispiel zeigt den Aufruf einer fiktiven Anwendung mit kurzen Optionen. Bei den gezeigten Optionen handelt es sich wieder um Flags, da sie keinen Wert definieren.

Application.exe -a
Application.exe -X -v -z -b

In dem nächsten Beispiel siehst du den Aufruf einer fiktiven Anwendung mit kurzen Kommandozeilenoptionen welche zudem Werte definieren.

Application.exe -a=Simple
Application.exe -a="Value with Spaces"
Application.exe "-a=Value with Spaces"
Application.exe -x=1023 -v=12 -z=Test

Zwischen dem Namen der Option, dem Gleichzeichen und dem Wert dürfen keine Leerzeichen stehen. Falls der Wert Leerzeichen enthalten soll, musst du den Wert oder die ganze Option in Anführungszeichen einschliessen.

Optionen des Konfigurationssystems

Das Konfigurationssystem bietet einige fest eingebaute Optionen, welche du in allen Produkten nutzen kannst:

--help, -h

Zeigt dir eine kurze Hilfe mit allen verfügbaren Optionen an. Siehe dazu Anzeigen der Hilfe.

--version

Zeigt den Produktnamen und die Version an. Siehe dazu Anzeigen der Version.

--config-file=<Datei>

Mit dieser Option fügst du zusätzliche Konfigurationsdateien hinzu. Siehe dazu Hinzufügen einer Konfigurationsdatei.

--config-dir=<Verzeichnis>

Mit dieser Option fügst du zusätzliche Verzeichnisse hinzu welche nach Konfigurationsdateien durchsucht werden. Siehe dazu Hinzufügen eines Konfigurationsverzeichnisses.

--config-trace

Mit dieser Option aktivierst du tracing Ausgaben des Konfigurationssystems auf der Konsole. Diese zusätzlichen Informationen können sehr nützlich sein, falls du ein Problem beim Einlesen der Konfigurationsdateien hast.

--pe-encode-config=<Datei>

Diese Option kodiert alle Passwörter in der angegebenen Datei. Du brauchst Schreibrechte auf die Konfigurationsdatei und das Verzeichnis in dem sie sich befindet, da die Datei direkt überschrieben wird. Siehe dazu Direktes Kodieren einer Konfigurationsdatei.

--pe-encode-password=<Passwort>

Mit dieser Option kodierst du manuell ein einzelnes Passwort. Siehe dazu Kodieren eines einzelnen Passworts.

--pe-show-key

Falls du nach wie vor die Password Encoder Anwendung verwenden möchtest, kannst du mit dieser Option den Schlüssel anzeigen welcher für die Kodierung benötigt wird. Siehe dazu Anzeigen und Speichern des öffentlichen Schlüssels.

Ältere Produkte unterstützen möglicherweise nicht alle hier gezeigten Optionen. Ist dieses Kapitel in der Dokumentation der von dir verwendeten Version eines Produkts vorhanden, werden alle Optionen unterstützt.

Anzeigen der Hilfe

Mit der Option --help, respektive -h kannst du dir eine kurze Übersicht aller von der Anwendung unterstützten Optionen anzeigen. Dies sieht dann beispielsweise so aus:

c:\> FileSystemWorkerCommand.exe --help
FileSystemWorkerCommand.exe [options] {jobFile}
Options:
--config-dir=... [list]
    Add another directory to scan for configuration files.
--config-file=... [list]
    Add another configuration file to parse.
--help, -h [boolean value]
    Displays help about command line arguments.
--output-mode=..., -o=... [string value]
    The mode for the console output.
--param=..., --parameter=..., -p=... [list]
    A custom parameter which can be used in placeholders of the job.
--version [boolean value]
    Displays the name and version of the application.

Anzeigen der Version

Mit der Option --version zeigst du den Produktnamen und die Version der Anwendung an. Falls du unsere Werkzeuge aus Skripten startest kannst du so die installierte Version abfragen.

Die Ausgabe sieht beispielweise so aus:

c:\> FileSystemWorkerCommand.exe --version
File System Worker Command - V1.5.13

Das Format der Ausgabe ist immer gleich, du kannst sie mit dem folgenden Regulären Ausdruck interpretieren.

(?i)^\s*([a-z0-9 ]+)\s+-\s+V(\d+\.\d+\.\d+)\s*$

Hinzufügen einer Konfigurationsdatei

Mit der Option --config-file fügst du eine weitere Konfigurationsdatei hinzu, die beim Start gelesen wird. Dabei gibst du als Wert einen relativen oder absoluten Pfad zu der Datei an.

Der Aufruf mit dieser Option kann so aussehen:

c:\> FileSystemWorkerCommand.exe --config-file=e:\configurations\fsw-a.conf_b.xml

Siehe auch Das IncludeFile Element.

Hinzufügen eines Konfigurationsverzeichnisses

Mit der Option --config-dir fügst du ein Verzeichnis hinzu, das beim Start nach Konfigurationsdateien durchsucht wird. Dabei gibst du als Wert einen absoluten Pfad zu einem Verzeichnis an.

Der Aufruf mit dieser Option kann so aussehen:

c:\> FileSystemWorkerCommand.exe --config-dir=e:\configurations

Sehe auch Das IncludeDirectory Element.

Kodieren von Passwörtern

Damit Passwörter nicht einfach aus einer Konfigurationsdatei kopiert werden können, lassen Sie sich Kodieren. Dadurch ist es deutlich schwieriger an das Passwort zu gelangen.

Bei der Kodierung handelt es sich um eine asymmetrische Verschlüsselung. Dabei werden die Passwörter mit einem öffentlichen Schlüssel verschlüsselt, der mit --pe-show-key angezeigt werden kann. Um so verschlüsselte Passwörter wieder zu entschlüsseln, wird der private Schlüssel benötigt, der direkt in die Anwendung eingebettet ist.

Dies erschwert das kopieren sehr, bietet jedoch keine absolute Sicherheit, da ein Softwarespezialist mit genügend Zeit und Erfahrung den eingebetteten privaten Schlüssel aus der Anwendung extrahieren kann. Die Kodierung der Passwörter bietet einen einfachen Schutz damit Mitarbeiter dieses nicht einfach aus einer zugänglichen Konfiguration kopieren, schützt jedoch nicht gegen kriminelle Aktivitäten.

Es ist daher wichtig, dass du die Konfigurationsdateien welche Passwörter enthalten so schützt, dass nur Administratoren und die Anwendung selbst diese lesen kann. Dazu bieten die verschiedenen Betriebssysteme passende Berechtigungen an die du auf die Dateien und Ordner anwenden kannst.

Direktes Kodieren einer Konfigurationsdatei

Mit der Option --pe-encode-config kodierst du alle Passwörter in einer Konfigurationsdatei. Die Konfigurationsdatei wird dabei mit der neuen Version überschrieben. Du brauchst daher Schreibrechte auf die Konfigurationsdatei und auf das Verzeichnis in dem sie sich befindet.

Die folgende Konfigurationsdatei enthält ein uncodiertes Passwort

ActiveDirectory.conf_b.xml
<?xml version="1.0" encoding="UTF-8" ?>
<Configuration
    version="1"
    xmlns="http://educateit.ch/software/BlueStone/Configuration/1">

    <Module name="ActiveDirectory">
        <List name="Servers">
            <ListEntry>
                <Value name="Domain">educateit.intra</Value>
                <Value name="Host">server01</Value>
                <Value name="UserName">administrator</Value>
                <Value name="Password">Secret Password</Value>
                <Value name="ObjectContext">educateit.intra</Value>
            </ListEntry>
        </List>
        ...
    </Module>
</Configuration>

Jetzt startest du die Anwendung welche das kodierte Passwort lesen soll mit der Option --pe-encode-config. In diesem Beispiel handelt es sich um EducateIT Raptor.

c:\> RaptorServer.exe --pe-encode-config=x:\configurations\ActiveDirectory.conf_b.xml
Encoded 1 entries in the configuration file.

Du bekommst eine Rückmeldung, wie viele Passwörter in der Datei ersetzt wurden. Nach dem Aufruf sieht die Konfigurationsdatei folgendermassen aus:

ActiveDirectory.conf_b.xml
<?xml version="1.0" encoding="UTF-8" ?>
<Configuration
    version="1"
    xmlns="http://educateit.ch/software/BlueStone/Configuration/1">

    <Module name="ActiveDirectory">
        <List name="Servers">
            <ListEntry>
                <Value name="Domain">educateit.intra</Value>
                <Value name="Host">server01</Value>
                <Value name="UserName">administrator</Value>
                <Value name="Password">◀PKEY▶RFpTRUFMRUQBAQAAABTBuX8uppk9NiwKaBUTTbvIFawjmwAAAQA1MRuf8EfC3l2LU92wnhmp
+KdYyO9gyqgg9Os9fV78YIgNu7biglUpZbEQez2VETpPCN5wevjrD+cYujIHqVmAJyV8mPr57EJSi
SR0pjpkmdy8ffOvwFB+5b6yvuKc0O+J6oTHhOwDll2XFJdqLgb3vLW4wd6D3d7BtX6D8hqcRVuQTk
XEZCXOHPAen3Sm/Pd9sq+3lhEsBFqzPlUX4K52KxFDL0VeDpsGD6WQ9yAisvmZKo3vxwMP2PPbEZI
fj2JvH8OfCpsqaacAtOC9MbVkxRl4gg4JlRZ3aHvvpYOV8FVYvQVg9Ch+6A7YS0TXParzVIIGQ5EI
62LqVDKmAtKtAAAAC2Flcy0yNTYtb2ZiAAAAEBHc1JZNso40u+sp22KoGSAAAAAj4QLgX6ZqsvpCW
Cg1EiUZyBmbASIxzhtzKqJR2mc184CI6ZQ=</Value>
                <Value name="ObjectContext">educateit.intra</Value>
            </ListEntry>
        </List>
        ...
    </Module>
</Configuration>

Du erkennst die kodierten Passwörter an dem Präfix ◀PKEY▶, und natürlich an der Länge.

Kodieren eines einzelnen Passworts

Einzelne Passwörter kannst du mit der Option --pe-encode-password kodieren. Dazu rufst du die Anwendung, welche das Passwort lesen soll folgendermassen auf:

c:\> RaptorServer.exe --pe-encode-password=SecretPassword
◀PKEY▶RFpTRUFMRUqBAqAAABTBuX8uppk9NiwKaBUTTbvIFawjmwAAAQB2JMuzdk4GLPxqE9v7eOsW
CiqALq7rEK3fGxF+FpWZmwCRvMyUQCJqNpOGJ+38BGUov35xkDrUO8I9wnisQV1Dn4lL/g2ZaS3AB
36RcgPHIzDOochL8LOvWv+CVtXEKnb8iz8Zaouqtn4C7Kshxad1VHOj5k2q/OXBQzqZuTxdY77/D8
1HLZBGdE5nYn5JR6ekDVan1qUvs3yX8iCRdGHcBALwPeJvaDfWFK1D8ctFpX1ybOWcMhLzxg/UDz4
FFq24mvntp17DYPyqeVXrS3wVbhAy0dFqUHxXJmC3qSTxQ9kWY+1bYazFEBtuERMciuqct24Q4qLP
ALDivGSZxBlcAAAAC2Flcy0yNTYtb2ZiAAAAEPaSfL8F+MZh7fydlhvETmAAAAAibsbB++t6Lxdeu
1V74XBckSGmgUF6k0+7SuI7cI1zvoxuKA==

Auf der Konsole siehst du jetzt das kodierte Passwort. Setze diesen Text an der Stelle ein, wo du das Passwort eingefügt hättest.

Anzeigen und Speichern des öffentlichen Schlüssels

Falls du nach wie vor die bisherige Password Encoder Anwendung verwenden möchtest, kannst du den öffentlichen Schlüssel mit der Option --pe-show-key exportieren.

c:\> RaptorServer.exe --pe-show-key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0FGYSFOCw2lda3AwH1aL
ZlnO//3s6qAgc6G+8XW12xagNFZPhuEorAdabeFH2EOCafHh4j2kJAuPIo2TyoBi
vTg7Q+q/4lQPy0en1NW63oTaJ1RB0SAMdp4Al8+izCKETzvzZMy01+SuVpYm4T7A
WiYw2WVXE7qoWIvEoe4W8o8J/S0003zHIioenHPc+DnBa7wifRNZagVZQmtGmaNX
lZfqXfXSUPhRtDbzaij+tJmm/qxOwSjm3aVdXKOmxgVwOfKCGanr2O/LReqkueI3
ci/00+Y6Nrt202Ztxti43uU4Vw8u5VUGrQ7rNUcXFwiXNxdalpLKcNFQbcNwpdcu
2wIDAQAB
-----END PUBLIC KEY-----

Speichere diesen Schlüssel indem du die Ausgabe in eine Datei umleitest:

c:\> RaptorServer.exe --pe-show-key > X:\Keys\Raptor.pkey

Schema der Konfigurationsdateien

Normalerweise ist das XML Schema für Konfigurationsdateien Teil jeder Installation. Es wird in das Applikationsverzeichnis mit dem Dateinamen ConfigurationB.xsd kopiert. Falls du es aus irgend einem Grund nicht erhalten hast, kannst du die Datei hier herunterladen:

Hier nochmals als Referenz, das XML Schema für die Konfigurationsdateien.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	attributeFormDefault="unqualified"
	elementFormDefault="qualified"
	targetNamespace="http://educateit.ch/software/BlueStone/Configuration/1"
	xmlns="http://educateit.ch/software/BlueStone/Configuration/1"
	xmlns:xs="http://www.w3.org/2001/XMLSchema">

	<xs:simpleType name="HostGroupName">
		<xs:restriction base="xs:string">
			<xs:pattern value="[-_a-zA-Z0-9]+" />
			<xs:minLength value="1" />
			<xs:maxLength value="64" />
		</xs:restriction>
	</xs:simpleType>

	<xs:simpleType name="ValueName">
		<xs:restriction base="xs:string">
			<xs:pattern value="[-_a-zA-Z0-9]+" />
			<xs:minLength value="1" />
			<xs:maxLength value="64" />
		</xs:restriction>
	</xs:simpleType>

	<xs:simpleType name="ModuleName">
		<xs:restriction base="xs:string">
			<xs:pattern value="[-_a-zA-Z0-9]+" />
			<xs:minLength value="1" />
			<xs:maxLength value="64" />
		</xs:restriction>
	</xs:simpleType>
	
	<xs:simpleType name="PlaceholderFlag">
		<xs:restriction base="xs:string">
			<xs:enumeration value="Replace">
				<xs:annotation>
					<xs:documentation>Replace all placeholders in the text of this value.</xs:documentation>
				</xs:annotation>
			</xs:enumeration>
			<xs:enumeration value="Ignore">
				<xs:annotation>
					<xs:documentation>Ignore all placeholders in the text of this value.</xs:documentation>
				</xs:annotation>
			</xs:enumeration>
		</xs:restriction>
	</xs:simpleType>
	
	<xs:complexType name="Value">
		<xs:simpleContent>
			<xs:extension base="xs:string">
				<xs:attribute name="placeholder" type="PlaceholderFlag" use="optional" default="Replace" />
			</xs:extension>
		</xs:simpleContent>
	</xs:complexType>

	<xs:complexType name="NamedValue">
		<xs:simpleContent>
			<xs:extension base="Value">
				<xs:attribute name="name" type="ValueName" use="required" />
			</xs:extension>
		</xs:simpleContent>
	</xs:complexType>

	<xs:complexType name="Group">
		<xs:sequence>
			<xs:group ref="Elements" minOccurs="0" maxOccurs="unbounded" />
		</xs:sequence>
	</xs:complexType>

	<xs:complexType name="NamedGroup">
		<xs:complexContent>
			<xs:extension base="Group">
				<xs:attribute name="name" type="ValueName" use="required" />
			</xs:extension>
		</xs:complexContent>
	</xs:complexType>

	<xs:complexType name="NamedList">
		<xs:choice>
			<xs:element name="ListEntry" type="Group" minOccurs="0" maxOccurs="unbounded" />
			<xs:element name="Value" type="Value" minOccurs="0" maxOccurs="unbounded" />
		</xs:choice>
		<xs:attribute name="name" type="ValueName" use="required" />
	</xs:complexType>

	<xs:group name="Elements">
		<xs:choice>
			<xs:element name="Value" type="NamedValue" />
			<xs:element name="Group" type="NamedGroup" />
			<xs:element name="List" type="NamedList" />
		</xs:choice>
	</xs:group>
	
	<xs:complexType name="Module">
		<xs:sequence>
			<xs:group ref="Elements" minOccurs="0" maxOccurs="unbounded" />
		</xs:sequence>
		<xs:attribute name="name" type="ModuleName" use="required" />
		<xs:attribute name="hostGroup" type="HostGroupName" use="optional" />
	</xs:complexType>

	<xs:complexType name="HostGroup">
		<xs:sequence>
			<xs:choice minOccurs="1" maxOccurs="unbounded">
				<xs:element name="HostAddress" type="xs:string" />
				<xs:element name="Network" type="xs:string" />
			</xs:choice>
		</xs:sequence>
		<xs:attribute name="name" type="HostGroupName" use="required" />
	</xs:complexType>
	
	<xs:complexType name="HostGroups">
		<xs:sequence>
			<xs:element name="HostGroup" type="HostGroup" minOccurs="0" maxOccurs="unbounded" />
		</xs:sequence>
	</xs:complexType>
	
	<xs:complexType name="Configuration">
		<xs:sequence>
			<xs:choice minOccurs="0" maxOccurs="unbounded">
				<xs:element name="Module" type="Module" />
				<xs:element name="IncludeFile" type="xs:string" />
				<xs:element name="IncludeDirectory" type="xs:string" />
				<xs:element name="HostGroups" type="HostGroups" />
			</xs:choice>
		</xs:sequence>
		<xs:attribute name="version" type="xs:integer" use="required" />
	</xs:complexType>

	<xs:element name="Configuration" type="Configuration" />
	
</xs:schema>

Fussnoten