Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
1 Einführung
2 Grundlagen der Sprachsyntax
3 Klassendesign
4 Weitere Datentypen
5 Multithreading
6 Collections und LINQ
7 Eingabe und Ausgabe
8 Anwendungen: Struktur und Installation
9 Code erstellen und debuggen
10 Einige Basisklassen
11 Windows-Anwendungen erstellen
12 Die wichtigsten Steuerelemente
13 Tastatur- und Mausereignisse
14 MDI-Anwendungen
15 Grafiken mit GDI+
16 Drucken
17 Entwickeln von Steuerelementen
18 Programmiertechniken
19 WPF – Grundlagen
20 Layoutcontainer
21 WPF-Steuerelemente
22 Konzepte von WPF
23 Datenbankverbindung mit ADO.NET
24 Datenbankabfragen mit ADO.NET
25 DataAdapter
26 Offline mit DataSet
27 Datenbanken aktualisieren
28 Stark typisierte DataSets
A Anhang: Einige Übersichten
Stichwort

Jetzt Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual Basic 2008 von Andreas Kuehnel, Stephan Leibbrandt
Das umfassende Handbuch
Buch: Visual Basic 2008

Visual Basic 2008
3., aktualisierte und erweiterte Auflage, geb., mit DVD
1.323 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1171-0
Pfeil 8 Anwendungen: Struktur und Installation
Pfeil 8.1 Bibliotheken
Pfeil 8.1.1 Projekte in einer Projektmappe
Pfeil 8.1.2 Zugriffsmodifikatoren
Pfeil 8.1.3 Einbinden einer Klassenbibliothek
Pfeil 8.2 Assemblies
Pfeil 8.2.1 Struktur einer Assembly
Pfeil 8.2.2 Globale Assemblies
Pfeil 8.3 Konfigurationsdateien
Pfeil 8.3.1 Die verschiedenen Konfigurationsdateien
Pfeil 8.3.2 Struktur einer Anwendungskonfigurationsdatei
Pfeil 8.3.3 Anwendungskonfigurationsdatei automatisch erstellen
Pfeil 8.3.4 Anwendungskonfiguarionsdatei auswerten
Pfeil 8.3.5 Editierbare, anwendungsbezogene Einträge mit <appSettings>
Pfeil 8.3.6 Versionsumleitung in einer Konfigurationsdatei
Pfeil 8.3.7 Die Herausgeberrichtliniendatei
Pfeil 8.4 Weitergabe mit MS-Installer
Pfeil 8.4.1 Weitergabeprojekte
Pfeil 8.4.2 Windows-Installer
Pfeil 8.4.3 Setup-Projekt
Pfeil 8.4.4 Editoren eines Weitergabeprojekts
Pfeil 8.4.5 Dateisystem-Editor
Pfeil 8.4.6 Der Registrierungs-Editor
Pfeil 8.4.7 Dateityp-Editor
Pfeil 8.4.8 Benutzeroberflächen-Editor
Pfeil 8.4.9 Editor für benutzerdefinierte Aktionen
Pfeil 8.4.10 Editor für Startbedingungen
Pfeil 8.5 ClickOnce-Verteilung
Pfeil 8.5.1 Erstellen einer ClickOnce-Anwendung
Pfeil 8.5.2 Die Installation einer ClickOnce-Anwendung


Rheinwerk Computing - Zum Seitenanfang

8.2 Assemblies Zur nächsten ÜberschriftZur vorigen Überschrift

Wenn Sie eine Konsolen-, Windows- oder Windows-Dienst-Anwendung entwickeln, wird eine EXE-Datei erzeugt. Ist das Projekt zum Beispiel vom Typ Klassenbibliothek, wird eine nicht eigenständig ausführbare DLL-Datei generiert. Die Kompilate werden, abhängig von der Konfigurationseinstellung, im Ordner /bin/Debug bzw. obj/Debug unterhalb des Projektordners gespeichert.

Die Interoperabilität von (D)COM basiert auf einem eigenen Typsystem und der Orientierung an Schnittstellen und nicht an Implementierungen. Die Schnittstellenbeschreibungen sind in der Registrierungsdatenbank abgelegt, der Programmcode getrennt davon im Dateisystem. Das Typsystem erlaubt keine unterschiedlichen Versionen derselben Komponente: Das ist die sogenannte DLL-Hölle. Wegen dieser Probleme führte .NET ein neues Konzept ein:

  • Code und Selbstbeschreibung einer Komponente bilden eine Einheit (Registry unnötig).
  • Verschiedene Versionen einer Komponente können parallel installiert und auch parallel ausgeführt werden (keine Abwärtskompatibilität).
  • Eine Anwendung muss selber wissen, welche Komponentenversionen sie nutzen kann. Die Laufzeitumgebung muss dementsprechend versionsrichtige Komponenten laden.

Diese Komponenten werden Assembly genannt. Ihre Selbstbeschreibung (inklusive Version und Sicherheitsrichtlinien) und die Beschreibung benötigter Komponenten (inklusive Version) erfolgt als ein Teil des Codes, der als Manifest bezeichnet wird. Es gibt zwei Assembly-Typen:

  • Private Assemblies die nur von einer Anwendung genutzt werden können und im selben Verzeichnis liegen müssen.
  • Gemeinsame Assemblies (globale Assemblies), die von allen Anwendungen genutzt werden können und im Global Assembly Cache (GAC) liegen.
    • Für eine Veröffentlichung im GAC ist ein kryptografischer Schlüssel Voraussetzung. Dieser gewährleistet, dass eine Assembly von einer anderen, zufälligerweise gleichnamigen Assembly eines anderen Entwicklers eindeutig unterschieden werden kann.

Rheinwerk Computing - Zum Seitenanfang

8.2.1 Struktur einer Assembly Zur nächsten ÜberschriftZur vorigen Überschrift

Um eine einfache und sichere Versionierung und Verteilung zu erreichen, muss die Selbstbeschreibung einer Assembly einige Informationen enthalten:

  • der Name, um die Assembly zu identifizieren
  • eine Angabe darüber, ob die vorliegende Assembly das ursprüngliche Original oder eine neuere Version ist
  • Abhängigkeiten von anderen Komponenten, inklusive deren Namen und Versionsnummern
  • Informationen über die von der Assembly exportierten Typen
  • Bezeichner aller Methoden, inklusive Parameternamen und -typen, und den Typ des Rückgabewertes

Diese Metadaten sind Daten, die andere Daten beschreiben. Beispiele dafür sind Datentypen und Standardwerte von Tabellenspalten. Eine Assemblierung hat damit drei Blöcke:

  • Metadaten, die die Assembly allgemein beschreiben (das Manifest)
  • Typmetadaten, die die öffentlichen Typen beschreiben
  • den IL-Code inklusive Ressourcen (z. B. Bilder, Tabellen für Fremdsprachenübersetzung)

Eine Assembly muss Metadaten enthalten, selbst der Code und die Ressourcen sind optional.

Manifest und Metadaten

Metadaten sind binär in der DLL- bzw. EXE-Datei (der Assembly) gespeichert. Sie werden von der Common Language Runtime benötigt, um Datentypen und Objekte überhaupt verwenden zu können. Sie lassen sich in zwei Gruppen einteilen:

  • Das Manifest, das die Struktur einer Assembly beschreibt, enthält unter anderem:
    • Typname
    • Versionsnummer
    • öffentliche Schlüssel
    • Liste aller Dateien, aus denen sich die Assembly zusammensetzt
    • Liste aller weiteren Assemblies, die an die aktuelle Assembly statisch gebunden sind
    • Sicherheitsrichtlinien, die die Berechtigungen an der Assembly steuern
  • Typmetadaten, die die Typen des IL-Codes innerhalb einer Komponente beschreiben. Das schließt den Namen des Typs, seine Sichtbarkeit, seine Basisklassen und die von ihm implementierten Schnittstellen ein.

Es spielt keine Rolle, in welcher Sprache eine Assembly entwickelt worden ist. Das Manifest verwischt die Spuren des zugrunde liegenden Quellcodes. Die Intermediate Language (IL) und die Common Language Runtime (CLR) schaffen mittels des Manifests die Voraussetzung für den problemlosen Austausch, ohne weitere Informationen zu benötigen.

IL-Disassembler

Das mit Visual Studio gelieferte Tool ildasm.exe, der sogenannten IL-Disassembler, macht die Metadaten sichtbar. In der Standardinstallation befindet er sich im Verzeichnis ...\Programme\Microsoft SDKs\Windows\v6.0A\Bin. Dieser Pfad ist in der Eingabeaufforderung bereits gesetzt, die Sie über den Startmenüpunkt StartAlle ProgrammeMicrosoft Visual Studio 2008Visual Studio ToolsVisual Studio 2008 Eingabeaufforderung öffnen. Entweder geben Sie hinter ildasm einen Dateipfad zu einer Assembly an, oder Sie öffnen die grafische Oberfläche durch Weglassen des Dateipfades. Zum Beispiel:

ildasm C:\MeineProjekte\MyFirstAssembly.exe

Sehen wir uns mit dem ILDASM-Tool das Manifest der folgenden Konsolenanwendung an, die in der Datei ClassA.vb die Main-Methode und eine Klasse ClassA enthält und in der Datei ClassB.vb die Klasse ClassB. Um den Informationsgehalt im Disassembler zu verdeutlichen, enthält der Typ ClassB insgesamt drei Variablendeklarationen mit unterschiedlichen Sichtbarkeiten.


'...\Applikation\ILdasm\ClassA.vb

Imports System.Data 
Namespace MyAssembly 
  Module Start 
    Sub Main() 
      Dim col As DataColumn = New DataColumn() 
      Console.WriteLine("Hallo Welt.") 
      Console.ReadLine() 
    End Sub 
  End Module 
  Public Class ClassA 
    Public intVar As Integer 
  End Class 
End Namespace

'...\Applikation\ILdasm\ClassB.vb

Public Class ClassB 
  Public intVar As Integer 
  Private lngVar As Long 
  Protected strText As String 
End Class

Der Name der Assembly ist ILdasm. Sehen wir uns jetzt an, was uns das ILDASM-Tool liefert, ohne dabei allzu sehr in die Details zu gehen (siehe Abbildung 8.2).

Abbildung 8.2 Anzeige des ILDASM-Tools

Unterhalb des Wurzelknotens, der den Pfad zu der Assemblierung angibt, steht das Manifest. Darunter ist der Knoten ILdasm, der in der Abbildung bis auf den Namensraum My vollständig geöffnet ist. Neben den Typmetadaten listet das Tool alle Variablen und Klassenmethoden auf – in unserem Beispiel nur die statische Methode Main aus Start sowie die mit .ctor bezeichneten Konstruktoren – und gibt den Sichtbarkeitsbereich der Variablen an. Der Rückgabewert der Methoden wird, getrennt durch einen Doppelpunkt, hinter dem Methodennamen angeführt.

Das Manifest sehen Sie nach einem Doppelklick auf den Manifest-Eintrag in einem neuen Fenster. Der Reihe nach werden zuerst alle externen Assemblies aufgelistet, von denen die aktuelle Anwendung abhängt, unter anderem auch System.Data. Die wichtigste Assembly mscorlib aus mscorlib.dll macht den Anfang.

.assembly extern mscorlib 
{ 
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                   // .z\V.4.. 
  .ver 2:0:0:0 
}

Jede gemeinsam genutzte Assembly im GAC hat einen öffentlichen Schlüssel. Im Manifest steht er hinter dem Attribut .publickeytoken in geschweiften Klammern. Neben dem Namen einer Assemblierung ist unter anderem auch der Schlüssel Teil ihrer Identität. Er sichert gleichzeitig die Identität des Komponentenentwicklers (siehe unten). Ein weiterer Teil der Identität ist die Version, die im Manifest im Attribut .ver gespeichert ist. Dadurch sind gleichnamige Assemblierungen verschiedener Versionen unterschiedlich und können nebeneinander existieren. Der Liste der externen Assemblierungen schließt sich im Block

.assembly ILdasm

eine Liste diverser Attribute an, mit denen die Assemblierung beschrieben wird. Die Attribute werden in den Projekteigenschaften oder der Datei AssemblyInfo.vb festgelegt.


Rheinwerk Computing - Zum Seitenanfang

8.2.2 Globale Assemblies topZur vorigen Überschrift

Eine globale Assembly steht allen .NET-Anwendungen zur Verfügung, ein Beispiel sind die Klassen des .NET Frameworks. Bereits vor der Kompilierung entscheiden Sie, ob eine Assembly privat oder öffentlich wird. Global wird sie durch die Installation in einem speziellen Verzeichnis: dem Global Assembly Cache (GAC). Der GAC ist ein Speicherort, an dem sogar mehrere unterschiedliche Versionen derselben Assembly installiert werden dürfen. Zu finden ist der GAC in folgendem Verzeichnis:

\<Betriebssystemordner>\assembly

Der Windows Explorer lässt uns nicht in das Verzeichnis assembly »hineinschauen«. Sie können jedoch an der Eingabekonsole die Struktur des GAC erkunden. Die Bibliotheksnamen werden unter Berücksichtigung der Metadaten auf die Verzeichnisstruktur abgebildet.


<Betriebssystemordner>\assembly\GAC_MSIL\ 
  <Bibliothek ohne Endung>\<Version>_<Kultur>_<Schlüssel>\Bibliothek.dll

Zum Beispiel finden Sie die Bibliothek System.Drawing.dll der Version 2.0.0.0 mit dem Schlüssel b03f5f7f11d50a3a und keiner Kulturangabe (neutrale Kultur) in folgendem Verzeichnis

C:\WINDOWS\assembly\GAC_MSIL\System.Drawing\2.0.0.0__b03f5f7f11d50a3a

Mit den Informationen zu Dateiname, Version, Kultur und öffentlichem Schlüssel aus dem Manifest der Anwendung sucht die CLR die passende Assembly im GAC. Wird die CLR nicht fündig, geht sie von einer privaten Assembly aus und sucht im Verzeichnis der Anwendung. Konfigurationsdateien beeinflussen diesen Suchprozess (siehe unten).


Hinweis
Wegen der eindeutigen Identifizierbarkeit werden die Namen von Assemblies mit einem Schlüssel auch starke Namen genannt.


Versionierung von Assemblies

Die Version einer Assembly besteht aus vier durch jeweils einen Punkt getrennten Zahlen:

  • Hauptversion
  • Nebenversion
  • Build
  • Revision

Versionen, die sich in einer der beiden ersten Zahlen unterscheiden, sind inkompatibel. Die beiden letzten Ziffern erfassen kompatible Korrekturen (siehe Abbildung 8.3).

Abbildung 8.3 Schema der Versionierung

Das Manifest einer Anwendung spezifiziert die Versionen benötigter Assemblies. Findet die CLR zur Laufzeit diese nicht, weicht sie auf kompatible Versionen aus (gegebenenfalls einer anderen Kultur). Scheitert dies auch, kann die Assembly nicht geladen werden.

Die Versionsnummer ist ein Attribut der Assembly und steht in der Datei AssemblyInfo.vb.

<Assembly: AssemblyVersion("1.0.1.0")>

Sie tragen sie entweder dort ein oder in dem Dialog aus Abbildung 8.4, den Sie über die Schaltfläche Assemblyinformationen auf der Karteikarte Anwendung der Projekteigenschaften finden. Nach dem Schließen des Dialogs werden die Informationen in die Datei AssemblyInfo.vb eingetragen.

Abbildung 8.4 Festlegen der Assemblyversion

Schlüsseldatei erzeugen

Globale Assemblies sind gekennzeichnet durch die Signierung mit einem binären Schlüsselpaar, das aus einem öffentlichen und einem privaten Schlüssel besteht. Nur der Besitzer des privaten Schlüssels kann eine neue »schlüsselrichtige« Version der Assembly erstellen.

Beim Kompiliervorgang wird ein Teil des öffentlichen Schlüssels (Token) in das Manifest geschrieben und die Datei, die das Manifest enthält, mit dem privaten Schlüssel signiert. Nutzer der Assembly brauchen nur den öffentlichen Schlüssel, der private Schlüssel dient »nur« zur Authentifizierung. Er sichert Ihre Arbeit – verwahren Sie ihn gut.

Öffentlicher und privater Schlüssel werden durch eine Schlüsseldatei beschrieben, die mit dem Tool sn.exe erzeugt wird. Sie können dieses Tool an der Kommandozeile aufrufen oder einfacher über die Auswahlbox Assembly signieren auf der Karteikarte Signierung der Projekteigenschaften. Über die darunterliegende Auswahlliste können Sie dann eine vorhandenen Schlüsseldatei wählen oder eine neue erstellen. Bei der Neuerstellung geben Sie einen Dateinamen an und können die Datei mit einem Kennwort schützen (siehe Abbildung 8.5).

Abbildung 8.5 Schlüsseldatei mit Visual Studio 2008 erzeugen

Beim Signieren einer Assembly haben Sie möglicherweise nicht immer sofort Zugriff auf den privaten Schlüssel. In diesem Fall nehmen Sie eine verzögerte Signierung vor, die zunächst nur den öffentlichen Schlüssel verfügbar macht. Markieren Sie hierzu den Optionsschalter Nur verzögerte Signierung. Das Hinzufügen des privaten Schlüssels wird auf den Zeitpunkt der Bereitstellung der Assembly verschoben.

Installation im GAC mit dem Tool gacutil.exe

Nachdem nun eine Schlüsseldatei in die Assembly eingebunden ist, kann das Kompilat im GAC installiert werden. Dazu haben Sie zwei Möglichkeiten:

  • das Kommandozeilenprogramm gacutil.exe des .NET Frameworks.
  • eine Installationsroutine mit dem Micosoft Windows Installer

Fangen wir mit der ersten Variante an. Wie alle anderen Tools findet man gacutil.exe unter:

\Programme\Microsoft SDKs\Windows\V6.0A\bin

Die allgemeine Aufrufsyntax lautet:


gacutil [Optionen] [Assemblyname]

Aus der Liste der Optionen ragen zwei besonders heraus: der Schalter /i, um die darauf folgend angegebene Assembly im GAC zu installieren, und der Schalter /u, um eine gemeinsam genutzte Assembly zu deinstallieren, zum Beispiel so:

gacutil /i MyGlobalAssembly.dll 
gacutil /u MyGlobalAssembly

Installation im GAC mit einer Setup-Routine

Visual Studio bietet die Projektvorlage Setup-Projekt an, die eine automatisch ablaufende Installationsroutine erzeugt. Die Projektdetails übergehe ich hier und lege den Fokus auf die Installation im GAC. Als Beispiel dienen eine winzige Bibliothek und eine Testanwendung. Die Projekteinstellungen der Bibliothek verwenden einen leeren Stamm-Namespace.


'...\Applikation\GacBibliothek\GacKlasse.vb

Namespace GacTest 
  Public Class GacKlasse 
    Public Function Version() As String 
      Return "Erste Version" 
    End Function 
  End Class 
End Namespace

'...\Applikation\GacAnwendung\Programm.vb

Module Programm 
  Sub Main(ByVal args() As String) 
    Dim g As New GacTest.GacKlasse() 
    For no As Integer = 1 To args.Length 
      Console.WriteLine("{0}: {1}", no, args(no – 1)) 
    Next 
    Console.WriteLine(g.Version()) 
    Console.ReadLine() 
  End Sub 
End Module

Wie beschrieben, ergänzen wir eine Schlüsseldatei, die im Projektmappen-Explorer zu sehen ist (siehe Abbildung 8.6).

Abbildung 8.6 Projektmappe mit Schlüsseldatei

Danach sollten Sie nicht vergessen, das Projekt noch einmal zu kompilieren. Der Projektmappe fügen Sie anschließend über ihren Kontextmenüpunkt HinzufügenNeues Projekt ein Setup-Projekt hinzu (siehe Abbildung 8.7).

Abbildung 8.7 Auswahl des Setup-Projekts

Nach dem Klick auf OK wird im Codeeditor der Dateisystemeditor des Setup-Projekts angezeigt (siehe Abbildung 8.8). Er fasst unter anderem alle zu installierenden kompilierten Dateien zusammen.

Abbildung 8.8 Ansicht des Dateisystem-Editors

Im Kontextmenü des linken Knotens Anwendungsordner wählen Sie zuerst Hinzufügen und danach Datei. Sie wählen die kompilierte EXE-Datei der Anwendung GacAnwendung. Danach ist diese sowie die Bibliothek als benötigte Komponente im rechten Teil zu sehen.

Im Kontextmenü des obersten Knoten Dateisystem auf Zielcomputer fügen Sie mit Speziellen Ordner hinzufügen das Verzeichnis Cacheordner für globale Assembly hinzu. Verschieben Sie die Bibliothek aus dem Anwendungsordner in diesen Ordner. Nach der Kompilation ist eine setup.exe-Datei im Ausgabeordner des Setup-Projekts. Installieren Sie nun durch deren Aufruf das Programm, oder nutzen Sie dazu den Punkt Installieren im Kontextmenü des Setup-Projekts (Sie brauchen Administratorrechte). Die Abbildung 8.9 zeigt, dass die Biblio-thek im GAC ist.

Abbildung 8.9 Klassenbibliothek »GacBibliothek« im GAC

Der Vorteil des Global Assembly Caches ist, dass andere Anwendungen ebenfalls dieselbe zentral registrierte GacBibliothek nutzen können. Beim Starten von GacAnwendung wird ein GacKlasse-Objekt erzeugt und die Methode Version aufgerufen. Erwartungsgemäß wird »Erste Version« ausgegeben.

Neue Version der globalen Assembly installieren

Angenommen, die erste Version von GacBibliothek sei bereits verteilt (unter anderem über GacAnwendung). Nun soll eine überarbeitete Klasse GacKlasse verteilt werden, hier simuliert durch die Rückgabe einer anderen Version:

Public Function Version() As String 
  Return "Zweite Version" 
End Function

Entweder Sie fügen einer neuen Projektmappe die beiden Projekte hinzu, oder Sie heben die installierte EXE-Datei zur späteren Verwendung auf. Nachdem Sie die Rückgabe geändert haben, setzen Sie die Version der Assembly GacBibliothek auf 2.0.0.0. Fügen Sie der Projektmappe ein neues Setup-Projekt hinzu, dem Sie nur GacBibliothek im Knoten Cacheordner für globale Assembly hinzufügen, nicht GacAnwendung.

Auch die neue Setup-Routine muss ausgeführt werden, damit sich die zweite Version von GeometricsObject in den GAC einträgt (siehe Abbildung 8.10).

Abbildung 8.10 Zwei versionsverschiedene Einträge im GAC

Die bereits installierte GacAnwendung nutzt weiterhin die erste Version der Bibliothek. Damit sie die zweite Version nutzt, muss eine Konfigurationsdatei geändert werden.



Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Visual Basic 2008
Visual Basic 2008
Jetzt Buch bestellen


 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Rheinwerk-Shop: Visual Basic 2012






 Visual Basic 2012


Zum Rheinwerk-Shop: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


Zum Rheinwerk-Shop: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Rheinwerk-Shop: Windows Presentation Foundation






 Windows Presentation
 Foundation


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern