Versionierung von Assemblies unter .NET

Versioning

Hintergrund

Vor dem Zeitalter von .NET, also in den 1990er Jahren und davor, wurden bei der Installation von Anwendungen vielfach verwendete Bibliotheken (DLLs) der Anwendungen im Windows-Systemverzeichnis des PCs abgelegt und in die Windows-Registry eingetragen. Der Grund, warum viele Software-Hersteller dies taten, war u.a. um Speicherplatz zu sparen, der zu der Zeit noch in der Regel sehr wertvoll war. Durch diese einfache Ablage diverser DLL-Dateien im Windows-Systemverzeichnis waren allerdings die Möglichkeiten für die Verwaltung von verschiedenen Versionen einer Bibliothek sehr beschränkt, da sich während ihres Lebenszyklus beispielsweise ihre Schnittstelle bzw. der Einstiegspunkt zwischenzeitlich geändert haben konnte. Eine Windows-Anwendung hatte nämlich keine Möglichkeit herauszufinden, ob die in einer DLL-Bibliothek enthaltenen Datentypen wirklich die selben Typen waren, mit denen die Anwendung erstellt wurde. Infolgedessen konnte eine neue Version einer Software-Komponente eine ältere Version davon überschreiben und damit die Anwendung zum Absturz bringen.

Um so größer eine entwickelte Anwendung durch das Hinzufügen neuer Funktionen usw. über die Jahre selbst wurde und diese zum Beispiel darüber hinaus noch DLL-Bibliotheken von Dritt-Herstellern einsetzte, war man als Software-Hersteller - rein technisch betrachtet - seit Ende der 1990er Jahre eigentlich nicht mehr in der Lage zu sagen, dass die installierte Anwendung wirklich zu 100% frei von Seiteneffekten mit anderen installierten Applikationen auf dem verwendeten Windows-System waren. Da schuf auch u.a. der Einsatz von dedizierten Merge-Modulen bei der Installation von Bibliotheken nur bedingt Abhilfe, weil sich auch hier nicht alle Software-Hersteller an das Vorgehen gehalten haben.

Dieses Problem ist in der Entwicklerwelt besser bekannt als die berühmt-berüchtigte DLL-Hell, welche mit Einführung und Nutzung des .NET-Frameworks der Vergangenheit angehören sollte.

Weiterlesen

Das Intel HEX-Format

Das Intel Hex-Object Format dient zum Übertragen von binären Daten in der Regel über eine serielle Schnittstelle. Mir persönlich ist es seit Ende der 1990er Jahre geläufig, wo ich mich erstmals intensiv mit Mikroprozessoren beschäftigt habe. Laut einer Revision der orignalen Spezifikation von Intel 1988, handelt es sich bei dem hexadezimalen Objektdateiformat "um eine Möglichkeit, eine absolut binäre Objektdatei in ASCII darzustellen. Da die Datei in ASCII anstatt in Binärform vorliegt, ist es möglich, die Datei auch auf Medien wie z.B. Papierstreifen, Lochkarten usw. zu speichern". Wie man anhand der Formulierung sieht, ist das Format also schon recht alt, Lochkarten und dergleichen spielen zum Glück schon eine ganze Weile keine Rolle mehr in der Informatik. wink

Intel HEX-Dateien werden auch heute noch hauptsächlich im Umfeld der Embedded-Programmierung z.B. bei 8-Bit- und 16-Bit-Prozessoren verwendet, um generierte Programmierdaten der erstellten Programme für diese Prozessoren, EPROMS und ähnliche Bausteine zu speichern. Durch spätere Erweiterungen der Spezifikation wurden sogar noch 32-Bit-Prozessoeren der x86er-Serie von Intel mit berücksichtigt.

Weiterlesen

Asynchrone Programmierung in .NET C#

Neben den Gründen der technischen Anforderungen an eine Applikation, gibt es bereits seit Mitte der 2000er Jahre einen weiteren Grund, der immer mehr an Bedeutung gewonnen hat, nämlich die bessere Ausnutzung von modernen CPU-Architekturen (Multi-Cores) für ihre Beschleunigung. Um diese Technologien ausnutzen zu wollen, wurde dadurch das Schreiben von Multi-threaded Applikationen notwendig – also das Arbeiten mit mehreren Threads in Programmen.

Der Einsatz von Threads ist nützlich und sinnvoll, wenn lang andauernde Operationen stattfinden, die die Programmausführung blockieren (z.B. längere Berechnungen im Sekundenbereich, Warten auf bestimmte Bedingungen im System / Lauschen auf dem Netzwerk-Port usw.). Aber der Einsatz von klassischen Threads ist jedoch generell schwierig zu verstehen, denn ein bloßer Blick auf den Code reicht oft nicht - frei nach dem Motto: 1. Thread anlegen -> 2. Thread starten -> 3. Beten. wink

Die Synchronisation gemeinsam genutzter Resourcen erfordert grundsätzlich große Sorgfalt!

Der Einsatz von Threads ist beispielsweise widerum nicht sinnvoll, wenn es zu viele Abhängigkeiten zwischen den Threads gibt, denn Abhängigkeiten führen zu Blockierung von Code. In diesem Fall wartet ein Thread darauf, das ein anderer seine Arbeit beendet. Der Vorteil der asynchronen Ausführung verschwindet dann, beziehungsweise ist nicht mehr gegeben. Die Komplexität des Systems wird somit unnötig vergrößert, da viele Threads aufeinander abgestimmt werden müssen. In solchen Softwarekonstruktionen ist mitunter wochenlanges Debugging keine Seltenheit.

Dieser Umstand ist u.a. auch die Motiviation für dieses Tutorial gewesen, da ich vor nicht allzu langer Zeit bei Reviews von .NET C#-Projekten immer wieder Codeartefakte dazu fand, welche konzeptuell aus der klassischen Windows-Programmierung der 90er Jahre stammen und aus heutiger Sicht allein schon 'merkwürdig' aussehen. Mitunter kamen noch solche Konstrukte wie der Einsatz von while-Schleifen mit 'Thread.Sleep(1)', 'DoEvents()' und Ähnliches zum Einsatz, um auf die Beendigung von Vorgängen zu warten, die gerade irgendwo anders laufen.

Da das .NET-Framework seit seiner Erstveröffentlichung 2002 ordentlich gewachsen ist, sehen sich heutzutage gerade Einsteiger oder Umsteiger bereits allein mit 3 verschiedenen Implementationsmustern für die asynchrone Verarbeitung von Vorgängen konfrontiert, welche im .NET-Framework über die Jahre hinweg Einzug gehalten haben. Bevor nun auf moderne Konzepte und Hinweisen zu deren effizientem Einsatz eingegangen wird, erfolgt deshalb vorab nochmal etwas Aufklärung bezüglich der verschiedenen existierenden Features für asynchrone Programmierung unter .NET C#. Da dieser Themenkomplex ansonsten recht umfangreich ist und mittlerweile auch zahlreiche Literatur etc. dazu existiert, fokussiert sich dieses Tutorial nur auf ein paar wesentliche Punkte.

Weiterlesen

Logging mit log4net unter .NET

log4net ist Teil des Apache "Logging Services"-Projektes bei der Apache Software Foundation. Das Projekt "Logging Services" dient der Bereitstellung von sprachenübergreifenden Logging-Diensten für das Debugging und die Protokollierung von laufenden Applikationen. Das Projekt startete ursprünglich mit dem log4j-Framwork für Java, welches 1995 entwickelt wurde und seitdem gepflegt und kontinuirlich erweitert wird. Bei log4net handelt es sich also um dessen Portierung in das .NET Ökosystem. Unter .NET existieren natürlich auch andere Möglichkeiten zur Protokollierung von Applikationen – neben log4net gibt es weitere etablierte Logging-Frameworks, zum Beispiel „NLOG“ oder auch „Logging Block“ der Microsoft Enterprise Library. Generell bieten Logging-Frameworks deutlich mehr Flexibilität, als eine schnelle Implementierung von Hand, beispielsweise um sogenannte, frei konfigurierbare Appender, also "Wohin" soll denn geloggt werden. Das folgende Tutorial gibt einen schnellen Einstieg in log4net.

Weiterlesen

Demoszene "Reloaded" (2016)

2016 gab es nochmal eine Rückbesinnung zur alten Demoszene-Zeit. Zusammen mit meinem alten Kumpel Sven, damaliges Gründungsmitglied, haben wir noch einmal Diabolic Force aufleben lassen und die Demoparty Evoke 2016 in Köln besucht. Natürlich musste auch ein Release her - ohne sind wir nie zu einer solchen Party gefahren. Es entstand eine Demo als Reminiszenz an alte Demos und Intros aus den frühen 90er Jahren. Nach zuletzt 18 Jahren Abstinentz in zwei Wochen "mal eben nebenher" zusammengeklotzt, aber wir hatten wieder viel Spaß. cool
Darüber hinaus entstand von uns eine Dokumentation mit über 90 Minuten Länge über die Demoszene auf der Evoke 2016, zu sehen auf Youtube.

  • 1
  • 2
Diese Seite enthält Cookies. Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren und die Zugriffe auf unsere Website zu analysieren.
Akzeptieren Ablehnen