Home
Themen
Angebote
Downloads
News & Blogs
    ZfS News
    .NET & C#
    ASP.NET & Sharepoint
    ADO.NET & Datenbanken
    Windows
    Lehre
    Blogs nach Personen
Informatiklandkarte
DBWorld Map
.NET Glossar
Wir über uns
Kontakt
Newsletter

News

Monday, July 07, 2008

Zweiter Teil der HowTo-Serie „Interoperabilität der .NET-Präsentations-APIs“ jetzt als Download  #

Ab heute steht der zweite Teil der HowTo-Serie "Interoperabilität der .NET-Präsentations-APIs" als Download zur Verfügung.

Dieses HowTo-Dokument beschreibt, wie bestehende Windows-Forms-Applikationen um Steuerelemente der Windows-Presentation-Foundation (WPF) erweitert werden können.Gleichzeitig werden Grenzen und Nutzen der Interoperabilität dieser zwei konkurrierenden Präsentations-APIs aufgezeigt und diskutiert.

Der erste Teil der HowTo-Serie beschäftigt sich mit der Integration von Windows-Forms-Steuerelementen in eine WPF-Applikation.

Wednesday, May 07, 2008

Erster Teil der HowTo-Serie „Interoperabilität der .NET-Präsentations-APIs“ jetzt als Download  #

In letzter Zeit wurden von Schulungsteilnehmern verstärkt Themen rund um die Windows Presentation Foundation (WPF) und Unterschiede zu bzw. ein mögliches Zusammenspiel mit den Windows-Forms nachgefragt.

Aus diesem Grund haben wird zu diesem Thema jetzt ein HowTo-Dokument verfasst, das die Möglichkeiten beschreibt, Windows-Forms-Elemente in einer WPF-Applikation einzubetten und zu nutzen. Gleichzeitig werden Grenzen und Nutzen der Interoperabilität dieser zwei konkurrierenden Präsentations-APIs aufgezeigt und diskutiert. 

Ein zweites HowTo-Dokument, das in Kürze erscheinen wird, wird sich dann ergänzend mit der Integration von WPF-Steuerelementen in Windows-Forms-Applikationen auseinandersetzen.

 

Tuesday, May 06, 2008

.NET-Glossar wächst stetig weiter…  #

In der letzten Zeit ist unser Glossar wieder um interessante Beiträge gewachsen. Zu den aktuellsten gehören u.a.

Seit November 2007 bietet das Glossar übrigens auch die Möglichkeit, eigene Einträge zu verfassen oder vorhandene zu erweitern. Wir freuen uns, so ganz im Sinne des Web 2.0 das Glossar gemeinsam mit einer großen Community weiter ausbauen zu können!

Tuesday, April 29, 2008

Neues HowTo: GPS Daten in Windows Mobile auslesen  #

Es ist ein weiteres, neues HowTo Dokument mit dem Titel GPS Daten in Windows Mobile auslesen verfügbar. Beschrieben wird das Auslesen und Anzeigen von GPS Empfänger Daten über die serielle Schnittstelle. Zum HowTo gehört auch wieder eine Beispielanwendung.

Friday, April 25, 2008

Neues HowTo: Java Bibliothek in .NET nutzen  #

Es ist ein neues HowTo verfügbar, dass die Verwendung des Tools IKVM.NET zeigt. Mit IKVM.NET ist es möglich, Java Bibliotheken in .dll Files zu konvertieren und in .NET Projekten zu nutzen.
Zum HowTo gehört auch Beispielcode, der aus einer simplen Rechenbibliothek besteht, die in Java geschrieben ist und in .NET genutzt wird.

Wednesday, April 23, 2008

DBWorldMap aktualisiert  #

Wir haben unsere interaktive Landkarte zu Veranstaltungen im Bereich Datenbankforschung DBWorldMap komplett überarbeitet und eine neue Benutzerschnittstelle implementiert.

Das neue User-Interface basiert auf Silverlight und AJAX-Technologie. Dadurch sieht die neue Seite nicht nur besser aus, sondern ist auch gleichzeitig wesentlich performanter als die alte Version, da kaum noch "Postbacks", d.h. Interaktionen mit dem Server zum Aufbau einer neuen Seite durchgeführt werden müssen. Die Daten werden auf Client-Seite durch ein JavaScript-Programm abgefragt, auf Server-Seite arbeitet ein in C# implementierter Webservice.

Des Weiteren benutzen wir auch den Geo-Dient Microsoft Virtual Earth, der das interaktive Navigieren in den dargestellten Karten gestattet.

Tuesday, April 22, 2008

CampusLaunch an der RWTH Aachen  #

Am 29.4.2008 findet an der RWTH Aachen der CampusLaunch von Microsoft statt. Dabei werden die aktuellen Produkte von Microsoft, insbesondere die neue Version von Microsoft Visual Studio und das .NET-Framework 3.5 vorgestellt.

Der CampusLaunch wird von Microsoft Student Partnern (mit Unterstützung von Microsoft) organisiert.


Tuesday, April 08, 2008

Projekt-Praktikum für Informatik-Bachelor-Studenten gestartet  #

An der RWTH Aachen hat heute das vom ZfS Aachen angebotene Projekt-Praktikum für Informatik-Bachelor begonnen. Ziel des Praktikums ist die Entwicklung eines web-basierten Studenteninformationssystems für Studenten in Aachen. Dies soll neben Informationen zu interessanten Events oder Lokalen auch Infos zu Lehrveranstaltungen verwalten. Der Inhalt soll im Sinne des Web 2.0 von den Studenten selbst erstellt werden. In einem Forum sollen Studenten miteinander diskutieren können oder auch direkte Chats miteinander führen können.

Als Technologie wird das .NET-Framework in der Version 3.5 eingesetzt. Auch wenn Microsoft Visual Studio 2008 mit der neuen Version des .NET-Framework erst kürzlich erschienen ist, bietet die neue Version doch einige Neuerungen, die das Entwickeln von Web-Anwendungen einfachen machen. Ein wichtiges neues Feature in ASP.NET 3.5 ist zum Beispiel die AJAX-Bibliothek, mit der sehr einfach AJAX-basierte Web-Anwendungen mit .NET erstellt werden können. Wenn man zusätzlich das frei verfügbare AJAX Control Toolkit benutzt, hat man ein reichhaltige Auswahl an interaktiven Web-Controls.

Thursday, February 21, 2008

DreamSpark bietet kostenlos Microsoft-Software für Studenten  #

Seit zwei Tagen bietet Microsoft über DreamSpark allen Studenten kostenlosen Zugriff auf Entwickler- und Server-Software. Momentan sind auf DreamSpark
  • MS Visual Studio 2008,
  • MS Windows Server 2003,
  • MS Expression Studio und
  • XNA Game Studio 2.0
enthalten. Weitere Software soll in den nächsten Monaten folgen (z.B. SQL Server 2008, Windows Server 2008). Der Unterschied gegenüber dem schon lange bekannten Service MSDN AA (Academic Alliance) ist, dass über DreamSpark alle Studenten Zugriff auf die Software haben und nicht nur die von technischen Universitäten.

Wednesday, January 16, 2008

.NET unter Linux mit Mono  #

Im Download-Bereich haben wir ein neues HowTo zum Einsatz des .NET Frameworks unter Linux mit Mono zur Verfügung gestellt. Am Beispiel der in einem anderen HowTo vorgestellten Anwendung für UPnP-Devices als Web Services, zeigen wir Ihnen, wie diese Anwendung auf Mono unter Linux portiert werden konnte. Das HowTo-Dokument ist ausnahmsweise in englischer Sprache geschrieben.

Wednesday, December 19, 2007

HowTo-Artikel zu Web Services für UPnP Devices  #

Im Download-Bereich ist ein neues HowTo-Dokument verfügbar. Es stellt die Implementierung eines Proxy-Mechanismus für UPnP-Devices vor. Damit können die Dienste von UPnP-Devices, die im Netzwerk bereitgestellt werden, als Web Service verfügbar gemacht. Die vorgestellte Lösung ist dynamisch, d.h. es werden Web Services hinzugefügt bzw. entfernt, sobald ein UPnP-Device im Netzwerk registriert bzw. es verlässt.

Wednesday, October 24, 2007

OpenID für Microsoft SharePoint Server 2007  #

In unserem Download-Bereich haben wir ein weiteres HowTo-Dokument mit einer entsprechenden Beispielanwendung verfügbar gemacht. Thema ist diesmal die Verwendung von OpenID im Microsoft Office SharePoint Server 2007.

OpenID ist ein offener Standard zur Authentifizierung von Benutzern auf Websites. Anstatt verschiedene Logins für jede Website zu haben, soll ein Benutzer bei OpenID nur ein Benutzerkonto bei einem OpenID-Server benötigen. Der Benutzer braucht sich dann nur einmal bei dem OpenID-Server anzumelden, und kann dann mit diesen Benutzerkonto auf alle Websites zugreifen, die OpenID unterstützen. Um OpenID im Microsoft Office SharePoint Server 2007 zu nutzen, ist eine spezielle Implementierung des MembershipProvider notwendig, die wir Ihnen in diesem HowTo-Dokument beschreiben. Der Source-Code zu diesem HowTo ist ebenfalls auf unserer Website verfügbar.

Friday, September 21, 2007

Vortrag an der RWTH Aachen zum Thema Unit Testing  #

Gestern fand an der RWTH Aachen ein interessanter Vortrag zum Thema Unit Testing statt. Wolfram Schulte von Microsoft Research in Redmond stellte das Pex-Projekt von MSR vor, dass einen intelligenten Assistenten für Unit Tests entwickelt. Basierend auf parametrisierten Unit-Tests werden "normale" Unit-Tests generiert, die möglichst viele Code-Bereiche abdecken. Sollte der Test fehlschlagen, kann Pex Vorschläge zur Fehlerbeseitigung machen, da der Ablauf des Programms aufgezeichnet wurde.

Leider steht das Tool noch nicht öffentlich zur Verfügung. Aber vielleicht wird es in einer der zukünftigen Versionen von MS Visual Studio integriert ....

Tuesday, September 18, 2007

Weiteres HowTo zu Webparts für MOSS 2007 bzw. WSS v3  #

Nachdem es in den ersten beiden Teilen dieser HowTo-Reihe um Webparts allgemein und vor allem um deren grafische Oberfläche (oder die der Editoren) ging, geht es in diesem Teil um die Operationen des Webparts, die hinter den Kulissen ablaufen. Viele dieser Operationen, wie z.B. das Abfragen eines Webservices oder eine komplexe SQL-Anfrage, können mitunter viel Zeit in Anspruch nehmen. Oftmals ist es günstig, diese Operationen, die für den eigentlichen Webserver zum größten Teil aus Warten bestehen, im Hintergrund laufen zu lassen, während der Rest der Seite weiter abgearbeitet wird. In diesem HowTo zeigen wir Ihnen, wie Sie asynchrone Webparts erstellen können. Den Source-Code dazu finden Sie hier.

Tuesday, September 11, 2007

Editorparts für Webparts in MOSS 2007 erstellen  #

In einem früheren HowTo-Dokument hatten wir Ihnen gezeigt, wie Sie eigene Webparts für die Windows SharePoint Services 3 bzw. den Microsoft Office SharePoint Server 2007 erstellen können. In einem weiteren HowTo-Dokument geht es darum, wie Sie die Bearbeitung der Webparts für Ihre Benutzer vereinfachen können. Hierzu können Sie eigene Editoren, so genannte Editorparts erstellen, mit deren Hilfe der Benutzer die Eigenschaften Ihres Webparts im Browser bearbeiten kann. Ein solches Editorpart ersetzt dann die generischen Felder im Bearbeitungsbereich des Webparts. Das HowTo-Dokument und den Source-Code dazu können Sie auf unserer Webseite herunterladen.

Thursday, September 06, 2007

Neues HowTo-Dokument mit Beispiel zu Webparts in MOSS 2007  #

Auch für die neue Version der Windows SharePoint Services (WSS) bzw. des Microsoft Office SharePoint Servers 2007 (MOSS) lassen sich eigene Webparts entwickeln, welche die Funktionalität erweitern. Da Webparts aber seit ASP.NET 2.0 Teil der ASP.NET-Infrastruktur sind, hat sich bei der Erstellung gegenüber den Vorgängerversionen WSS 2.0 und MOSS 2003 einiges geändert. Dieses HowTo-Dokument zeigt, wie Sie mit Microsoft Visual Studio 2005 eigene Webparts für WSS bzw. MOSS erstellen können. Das in diesem How-To verwendete Webpart bindet den Suchservice von MSN als Webpart in SharePoint-Seiten ein. Sie können den Sourcecode des Webparts ebenfalls auf der Internetseite des ZfS Aachen herunterladen.

Wednesday, August 15, 2007

.NET Glossar-Gadget vom ZfS Aachen für BASTA! Innovation Award nominiert  #

Das ZfS Aachen entwickelte im Frühjahr diesen Jahres ein Sidebar-Gadget zum Zugriff auf das .NET Glossar des ZfS. Dieses Gadget ist auf sehr positive Resonanz gestoßen und wird von vielen Entwicklern eingesetzt. Aufgrund dessen wurde das Gadget nun für den BASTA! Innovation Award nominiert. Der BASTA! Innovation Award zeichnet Technologien, Forschungsthemen, Bücher oder Geschäftsideen aus, die einen Beitrag zur .NET-Welt leisten. Er ist insgesamt mit 20.000 EUR dotiert.

Wednesday, June 20, 2007

Webcast zum Thema Refactoring Teil 2 online  #

Seit kurzem ist der zweite Webcast zum Thema Refactoring online. Dieser kann hier heruntergeladen werden:

http://zfs.informatik.rwth-aachen.de/downloads_overview/downloads_webcasts.aspx

Dabei wird gezeigt, welche zusätzlichen Möglichkeiten durch den Einsatz des Plug-Ins "ReSharper" beim Refactoring geboten werden.

Whitepaper über die gemeinsame Nutzung von Java- und .NET-Webservices verfügbar  #

Seit kurzem ist ein Whitepaper verfügbar, welches anhand eines Szenarios aus dem Kundenbeziehungsmanagements aufzeigt, welche Probleme bei der Integration von Java- und .NET-Webservices im Rahmen einer Service-Orientierten Architektur (SOA) auftreten können und zeigt beispielhaft, wie diese gelöst werden können.

Das Whitepaper kann hier heruntergeladen werden:

http://zfs.informatik.rwth-aachen.de/downloads_overview/downloads_whitepaper.aspx

Friday, May 11, 2007

Sidebar Gadget für .NET-Glossar  #

Windows Vista bietet die Möglichkeit, am Rand des Desktops kleine Anwendungen (sogenannte Sidebar Gadgets) darzustellen. Diese Anwendungen basieren auf HTML und JavaScript und lassen sich somit mit relativ einfachen Mitteln selbst erstellen. In einem HowTo-Dokument zeigen wir Ihnen die wesentlichsten Schritte, die zur Erstellung eines Gadgets notwendig sind.

Als Beispiel haben wir ein Gadget für unser .NET-Glossar entwickelt. Damit können Sie direkt von Ihrem Desktop aus auf das Glossar zugreifen und die Bedeutung von Begriffen nachschlagen. Das .NET-Glossar-Gadget können Sie hier herunterladen.

 

Friday, April 20, 2007

Neues Whitepaper „Rich Internet Applications mit .NET 3.0“ jetzt als Download verfügbar  #

Wie im Blog vom 18. April bereits ausführlicher beschrieben, könnten so genannte „Rich Internet Applications“ (RIA) zur nächsten Softwaregeneration avancieren.

Das ab heute verfügbare Whitepaper „Rich Internet Applications mit .NET gibt einen Überblick darüber, mit welchen Technologien das .NET-Framework 3.0 die Entwicklung von RIA unterstützt.

Wednesday, April 18, 2007

Bedeutet Plattformunabhängigkeit bald nur noch Browserunabhängigkeit  #

Betrachtet man die Tendenz der Internetentwicklung insbesondere innerhalb der letzten 5-6 Jahre, so erkennt man einen ausgeprägten Trend hin zu visuell und funktionell reicheren, komfortableren und produktiveren Web-Applikationen.

So genannte „Rich Internet Applications“ (RIA) vereinen dabei typische Eigenschaften und Funktionalitäten von traditionellen Desktop- und klassischen Web-Applikationen und werden heute vielerseits als richtungsweisend für eine „nächste Softwaregeneration“ ausgelobt.

Auch das .NET-Framework stellt mit Technologien wie z.B. der „eXtensible Application Markup Language“ (XAML), der „XAML for Browser Application“ (XBAP) und insbesondere der „Windows Presentation Foundation Everywhere“ (WPF/E) sowie „ASP.NET AJAX“ (ehemals ATLAS) Möglichkeiten zur Verfügung, Applikationen zu implementieren, die als RIA direkt im Webbrowser ausgeführt werden können.

Neben dem Webbrowser benötigen viele RIA als einzige Softwarevoraussetzung ein Browser-PlugIn, um vornehmlich die grafisch zum Teil aufwendigen, interaktiven Benutzeroberflächen darzustellen.

Dieser allgemeine Trend lässt erahnen, dass ein Paradigmenwechsel von der Betriebssystemunabhängigkeit hin zur Browserunabhängigkeit stattfindet bzw. stattfinden wird. Die Bedeutung der Webbrowser als PlugIn-Container für verschiedenste Webformate (wie z.B. WPF/E, Flash, XBAP u.ä) und damit als primäre Ausführungsumgebung von Applikationen könnte dann zunehmend die allgemeine Betriebssystemdominanz – zumindest in bestimmten Anwendungsdomänen - ablösen.  

Zur Realisierung und zum Design plattformunabhängiger Applikationen müssen dann andere Überlegungen als bisher stärker in den Fokus der Anstrengungen gerückt werden:

-     Hat das für die Applikation notwendige PlugIn eine ausreichend große Marktpräsenz? Steht also für einen Großteil der Web-Browser das entsprechende PlugIn zu Verfügung?

-     Unterstützen die gängigen Webbrowser die für die Anwendung notwendigen Standards bzw. Quasi-Standards wie z.B. die DOM-Manipulation via Javascript im Kontext von AJAX-Anwendungen?

Die Anforderungen bzgl. plattformübergreifender Anwendungen werden sich dann von der Unterstützung unterschiedlicher Betriebssysteme hin zur Ausführbarkeit in möglichst vielen Webbrowsern verschieben.

 

Monday, March 12, 2007

Visual Studio 'Orcas' Preview verfügbar  #

Microsoft hat im Rahmen des "Community Technology Preview"-Programms eine Version der nächsten Visual Studio Version mit dem Codename "Orcas" verfügbar gemacht

CTP-Version von Visual Studio 'Orcas'

Das Programm wird als Virtual-PC-Image veröffentlicht und ist zwischen 650 MB und 6256 MB groß.

Visual Studio 'Orcas' liefert Unterstützung für Windows Vista und Office 2007. Weitere Highlights sind:

  • LINQ - "Language Integrated Query"
  • Unterstützung von C# 3.0
  • Neuerungen in ADO.NET
  • Unterstützung von C# Workflow Rules
  • Unterstützung von WPF (Windows Presentation Foundation) inklusive einem Designer
  • Unterstützung von WCF (Windows Communication Foundation) und WF (Workflow Foundation)

Visual Studio SP1 für Windows Vista  #

Microsoft hat das Servicepack 1 für Visual Studio 2005 für das Betriebssystem Vista veröffentlicht:

Visual Studio 2005 SP1 für Windows Vista

Bisher gab es nur eine Beta-Version. Diese muss vor Installation der engültigen Version deinstalliert werdenn.

Wednesday, January 17, 2007

Visual Studio 2005 Servicepack 1 verfügbar  #

Microsoft hat das erste Servicepack für Visual Studio 2005 veröffentlich. Es kann von den MSDN-Seiten heruntergeladen werden: Visual Studio 2005 SP1

Das Download des Servicepack ist nicht für User mit schmalen Bandbreiten empfehlenswert. In der Version für die Standard/Professional/Team-Server Editionen ist das SP1 stolze 431MB groß.

Es enthält mehr als 70 Verbesserungen, unter anderem kann der Code nun auch für die Core2Duo-Prozessoren optimiert werden.

Es gibt verschiedene Versionen des Servicepacks für die Express-Versionen, die Standard/Professional/Team-Server Editionen sowie für VS2005 unter Windows Vista. Das Servicepack für Vista liegt bisher jedoch nur in einer Beta-Version vor, es soll im Laufe des ersten Quartals als endgültige Version veröffentlicht werden.

Friday, January 12, 2007

Neue Einträge bereichern unser Glossar  #

Friday, December 15, 2006

XNA-Framework zur Erstellung von Spielen für XBox360 verfügbar  #

Seit dem 11. Dezember ist das "XNA Game Studio Express 1.0" verfügbar:

http://blogs.msdn.com/xna/archive/2006/12/11/xna-game-studio-express-has-been-released.aspx

XNA ist ein Framework um Spiele zu entwickeln, die sowohl unter Windows wie auch mit leichten Modifikationen auf der XBox360 lauffähig sind.

Dazu muss man das XNA Framework herunterladen und installieren. Zusätzlich muss eine Direct3D 9-fähige Grafikkarte im Rechner vorhanden sein (DirectX 9.0c und Shader Model 1.1).

Zusätzlich kann man die komplette Funktionalität des GSE nur mit der Visual C# Express-Version nutzen. Anwendungen können zwar mit Visual Studio 2005 kompiliert werden, man verliert allerdings einige Werkzeuge, die es nur in der Express-Version gibt.

Hier können das GSE und das XNA-Framework heruntergeladen werden: http://msdn.microsoft.com/directx/xna/gse/

Um per XNA und GSE erstellte Spiele auf der XBox360 abzuspielen, muss man Mitglied im sogenannten "XNA Creators Club" sein. Die erstellten Spiele müssen komplett im Source-Code und allen Ressourcen verteilt werden, das heisst die Weitergabe in Form einer kompilierten Anwendung ist nicht möglich. Dies schränkt in meinen Augen die Nützlichkeit ein, aber das kommende XNA Game Studio Professional wird da hoffentlich Abhilfe schaffen.

Weiter Fragen beantwortet das XNA FAQ.

XNA ist eine hoch-spannende Entwicklung und man kann sich überraschen lassen von der weiteren Entwicklung.  Überhaupt die Möglichkeit eine Konsole zu programmieren öffentlich zu machen ist revolutionär.

Friday, December 08, 2006

Kostenloses Tool zum Editieren von XML-Dateien verfügbar  #

Microsoft hat nun wieder ein Tool veröffentlicht, welches mehrere Jahre nicht auf MSDN verfügbar war: XML Notepad!

Es ist ein kleines, schnelles Tool zum Ansehen und Editieren von XML-Dateien. Es kann von der MSDN/Seite kostenlos herunter geladen werden.

Und hier erfährt man von Chris Lovett mehr über die Hintergründe, wieso das Tool nicht verfügbar war und wie die Entwicklungsgeschichte war: XML Notepad 2007 Design

 

Friday, December 01, 2006

ZfS beim "Tag der Informatik" in Aachen  #

Beim Tag der Informatik 2006 an der RWTH Aachen präsentiert das ZfS Aachen seine aktuellen Projekte. Unter anderem wurde das Projekt "Mobota" (Mobile Outdoor Training Assistant) vorgestellt. Mobota ist ein auf Microsoft Sharepoint basierendes Portal, auf dem Sportler (z.B. Läufer, Radfahrer) per GPS erfasste Touren verwalten können.

Eine mit dem .NET Compact Framework erstellte Anwendung erfasst während des Trainings die gefahrene bzw. gelaufene Route. Diese Anwendung läuft auf einem PDA mit GPS-Empfänger. Während des Trainings liefert die Anwendung Informationen zur absolvierten Strecke (z.B. Länge, Durchschnittsgeschwindigkeit). Nach dem Training kann die Route auf den Sharepoint-Server geladen werden. Die auf dem Server laufende ASP.NET-Webanwendung ermöglicht die Auswertung der Trainingsdaten und den Austausch der Routen zwischen verschiedenen Teilnehmern.

Thursday, November 30, 2006

Neue interessante & lesenswerte Glossareinträge  #

Damit Sie auch weiterhin den Überblick behalten, wächst unser Glossar ständig weiter.

Unter anderem finden Sie nun Erklärungen zu den folgenden neuen Einträgen:

 

Friday, November 24, 2006

Verzögertes Signieren von Assemblies oder wie man den Entwicklungsaufwand öffentlicher Assemblies reduziert  #

Delayed Signing bezeichnet eine Technik, um Assemblies teilweise zu signieren, z.B. wenn sich diese noch in der Entwicklungsphase befinden,
Beim Signieren eines Assemblies wird mit Hilfe eines öffentlichen und eines privaten Schlüssels zum einen das so genannte Public Key Token in das Manifest eines Assemblies geschrieben und zum anderen wird eine mit Hilfe des privaten Schlüssels erstellte digitale Signatur in den PE-Header des Assemblies eingetragen, die über den öffentlichen Schlüssel des Assemblies validiert werden kann. Zum Erstellen dieser digitalen Signatur benötigt man demnach das öffentliche/private Schlüsselpaar während zur Validierung dieser Signatur der öffentliche Schlüssel ausreicht.

Signierte Assemblies können in den Global Assembly Cache (GAC) installiert werden und andere .NET-Applikationen können über den Strong Name zudem die exakte Version dieses Assemblies einbinden und referenzieren. (weitere Infos zum Signieren von Assemblies finden sich im Beitrag vom 28.08.2006) Einmal signierte Assemblies können nicht mehr geändert werden, da sich die digitale Signatur nach der Änderung mit dem öffentlichen Schlüssel nicht mehr auflösen lässt. Mit anderen Worten können einmal signierte Assemblies nicht mehr geändert werden, ohne dass die digitale Signatur ihre Gültigkeit verliert oder – im Kontext des Entwicklungsprozesses - nach jeder Assembly-Änderung muss diese erneut digital signiert werden.
Um die Funktionalitäten des öffentlichen Assemblies aber bereits während des Entwicklungsprozesses zu testen ohne dabei fortlaufend das Assembly dem teilweise aufwändigen Prozess der Signierung zu unterziehen und damit auf den mitunter streng geheimen privaten Schlüssel zugreifen zu müssen, kann das Public Key Token über den Prozess des Delayed Signing eingebunden und ein Platzhalter für die digitale Signatur in den PE-Header des Assemblies eingetragen werden. So können Assemblies zu Testzwecken auch ohne digitale Signatur installiert und von anderen .NET Applikationen referenziert werden.

Vor dem offiziellen Release des Assemblies wird der Platzhalter dann schließlich durch die echte digitale Signatur ersetzt.
Um ein Assembly so zu signieren, sind im Wesentlichen die folgenden Schritte notwendig:

 

1. Compiler-Anweisungen über Attribute im Quelltext definieren

 

using System.Reflection;

 

[assembly:AssemblyKeyFile("keys.snk")]

[assembly:AssemblyDelaySignAttribute(true)]

 

Das erste Attribut AssemblyKeyFile ist auch bei der „normalen“ Signierung von Assemblies notwendig. Das Public Key Token des öffentlichen Schlüssels wird in das Manifest des Assemblies eingetragen.

Das zweite Attribut AssemblyDelaySignAttribute sorgt nun dafür, dass der Compiler Platz für die spätere digitale Signatur im PE-Header reserviert.

 

2. Das Assembly zur Skip Verification List hinzufügen, um die Verifizierung dieses Assemblies anhand der digitalen Signatur zu unterdrücken (z.B. mit dem Kommandozeilen-Werkzeug Strong Name Utility)

 

sn –Vr assemblyname.dll

 

In diesem Beispiel sorgt die Option –Vr dafür, dass das Assembly assemblyname.dll der Skip Verification List hinzugefügt wird.

Allerdings sollte man nicht allzu sorglos Assemblies dieser Liste hinzufügen. Ein schädliches Assembly könnte die Identität eines Assemblies aus dieser Liste vortäuschen und so ungewollt die Verifizierung umgehen.

 

Mit der Option -Vu können Assemblies wieder aus der Skip Verification List gelöscht werden:

 

sn –Vu assemblyname.dll

 

Hinweis: Eine Übersicht aller Optionen des Strong Name Tools erhalten Sie auf den MSDN-Seiten.

 

3. Nach Finalisierung des Assemblies die echte digitale Signatur einfügen.

 

sn –R assemblyname.dll keypair.snk

 

Schließlich erhält das Assembly vor der Auslieferung noch die echte digitale Signatur, die den Platzhalter ersetzt.

 

Friday, November 03, 2006

Webcast Refactoring unter VisualStudio 2005 Teil 1 verfügbar  #

Ab sofort ist ein neuer WebCast zum Thema Refactoring verfügbar.

Der Inhalt gliedert sich folgendermassen:

  • Was ist Refactoring?
  • Refactoring: “Rename …”
    • Umbenennung einer Methode
    • Umbenennen einer Klassenvariable
  • Refactoring: “Extract Method …”
    • Extrahieren einer Methode ohne Parameter
    • Extrahieren einer Methode mit einem Parameter

Friday, October 20, 2006

Den Überblick behalten mit dem online .NET-Glossar  #

Ab sofort hilft Ihnen unser .NET-Glossar, die Orientierung im Dschungel der Akronyme und Konzeptbegriffe zu behalten. Geläufige Akronyme, aber auch allgemeine Konzepte und Begriffe aus der IT- und .NET-Welt werden in diesem Glossar erläutert und mit Hintergrundinformationen angereichert.

Zusätzlich finden Sie an einigen Stellen auch Verweise auf weiterführende ZfS-Dokumente, die das Thema aufgreifen und vertiefen. Zum Download dieser Dokumente ist eine kostenlose Registrierung erforderlich.

Wir starten mit einer ersten, übersichtlichen Version und werden das Glossar schrittweise ausbauen und verfeinern.

Testen Sie jetzt unser .NET-Glossar!

 

 

Thursday, October 12, 2006

Neuer Webcast zum .NET-Sicherheitskonzept „Code Access Security“  #

In diesem Webcast erfahren Sie, welche grundlegenden Konzepte hinter der Code Access Security des .NET-Frameworks stecken und welche Schritte notwendig sind, um Ihre lokalen Sicherheitseinstellungen für verwaltete Applikationen anzupassen.

Dieser Webcast ist in unserem Downloadbereich für angemeldete Nutzer verfügbar.

Nutzen Sie unser Anmeldeformular, um sich kostenlos anzumelden. Sie haben dann uneingeschränkten Zugriff auf alle Dokumente und Beispielanwendungen aus unserem Downloadbereich!

 

Thursday, October 05, 2006

Neue Möglichkeiten mit Office 2007  #

Das neue Office 2007 Paket bietet neben neu konzipierten GUI-Elementen und einem neuen Look&Feel viele weitere Neuerungen, von denen ich heute eine der aus meiner Sicht interessantesten kurz vorstellen möchte.

Ab der neuen Office Version werden Dokumente zum ersten Mal standardmäßig in dem XML-basierten Datenformat OfficeXML gespeichert. In diesem Format gespeicherte Office-Dokumente bestehen aus einer Reihe von XML-Dateien und zugehörigen Projekt-Dateien (wie z.B. Bilder), die anschließend im Falle von z.B. Word 2007 als .docx oder .docm Dateien (ZIP-)komprimiert werden. Dieses neue, offene Datenformat vereinfacht z.B. die automatische Erstellung und Bearbeitung von Office-Dokumenten sowie deren Integration in die unternehmensweite Prozess-Landschaft. Ein weiterer Vorteil dieses neuen Speicherformats liegt in den Möglichkeiten, die z.B. durch Schemavalidierungen und Stylesheet-Transformationen gegeben sind. So lassen sich Office-Dokumente über entsprechende Tranformations-Regeln für prinzipiell fast beliebige Ausgabeformate automatisch aufbereiten.

Zusammen mit den Möglichkeiten, die sich aus der Integration eigener .NET-Assemblies (Stichwort: Visual Studio Tools für Office (VSTO)) in Office-Dokumente bzw. Applikationen ergeben (z.B. die Suche in lokalen Datenbanken aus einer Excel-Tabelle heraus), lassen sich hieraus zahlreiche interessante und zum Teil neue Nutzungsszenarien der Office-Applikationen entwickeln.

Wer die Office 2007 Beta-Version testen möchte, kann sich auf den Microsoft-Seiten bis zum 31. Oktober registrieren und gegen eine geringe Downloadgebühr herunterladen und testen. Die Beta-Version kann bis zum 01. Februar 2007 getestet werden.

 

Thursday, September 28, 2006

C#-FAQ: Formatierung von Datumsangaben  #

Die Darstellung des aktuellen Datums wird vornehmlich durch zwei Faktoren beeinflusst:

 

  1. durch die zu verwendende Sprache bzw. Kultur
  2. durch eine explizite Formatangabe

Mit dem Beitrag vom 17.08.2006 haben wir bereits die Methode String.Format()zur Formatierung von Fließkommazahlen vorgestellt. Die gleiche Methode kann auch der Formatierung von Datumsangaben dienen. Schauen wir uns die Signatur dieser Methode an, erkennt man, dass als erster Parameter ein Objekt erwartet wird, das die Schnittstelle IFormatProvider implementiert:

 

public static string Format(IFormatProvider provider, string format, params object[] args);

 

Das .NET-Framework stellt unter dem Namespace System.Globalization zwei Klassen zur Verfügung, die diese Schnittstelle implementieren, die im Kontext der Formatierung von Datumsangaben von besonderer Bedeutung sind:

 

  1. CultureInfo
  2. DateTimeFormatInfo

Während die erste Klasse CultureInfo Informationen über eine bestimmte Kultur bereitstellt, definiert die zweite Klasse DateTimeFormatInfo das Format der Anzeige durch die Angabe eines Standardformatbezeichners. Die wichtigsten dieser Standardformatbezeichner wollen wir im Folgenden etwas genauer betrachten. Wir nutzen dazu eine andere überladene Methode String.Format, die als Parameter lediglich den Formatbezeichner und das Datum erwartet. Die in den Systemeinstellungen definierte Kultur wird dabei für die landesspezifische Formatierung genutzt.

 

  1. Console.WriteLine(String.Format("{0:d}", DateTime.Now));

            Ausgabe: kurzes Datum: 04.09.2006

 

  1. Console.WriteLine(String.Format("{0:D}", DateTime.Now));

            Ausgabe: langes Datum: Montag, 4. September 2006

 

3. Console.WriteLine(String.Format("{0:f}", DateTime.Now));

 

            Ausgabe: langes Datum inkl. Zeitangabe: Montag, 4. September 2006 09:39

 

4. Console.WriteLine(String.Format("{0:m}", DateTime.Now));

 

            Ausgabe: Tag und Monat: 04 September

 

  1. Console.WriteLine(String.Format("{0:T}", DateTime.Now));

            Ausgabe: Zeitangabe inkl. Sekunden: 09:40:44

 

Weitere Standardbezeichner sind z.B. „t“ (Zeitangabe ohne Sekunden), „y“ (Monat und Jahr) oder „g“ (Datum inkl. Zeitangabe).

 

Um die Formatierung länderspezifisch zu gestalten, muss der Methode String.Format nun ein CultureInfo-Objekt übergeben werden, das die entsprechende Kultur beschreibt. Das folgende Listing definiert ein amerikanisches CultureInfo-Objekt und gibt das aktuelle Datum in einem für den US-amerikanischen Raum typischen Format aus:

 

CultureInfo culture = new CultureInfo("en-US");

Console.WriteLine(String.Format(culture, "{0:d}", DateTime.Now));

 

Die Ausgabe dieses Zweizeilers ist: 9/4/2006.

 

Neben diesen Standardformatbezeichnern lassen sich auch analog zur Formatierung von Fließkommazahlen eigene Formatierungsanweisungen definieren.

 

Hinweis: eine detaillierte Übersicht über die Standardformatbezeichner zur Formatierung von Datumsangaben findet es sich auf den MSDN-Seiten unter http://msdn2.microsoft.com/en-us/library/system.globalization.datetimeformatinfo.aspx. Eine Übersicht über die Länderkennungen findet sich auf den MSDN-Seiten unter http://msdn2.microsoft.com/en-us/library/system.globalization.cultureinfo.aspx.

Thursday, September 07, 2006

Microsoft verschenkt 5000 Exemplare der Visual Studio 2005 Standard Edition  #

Bei MSDN-Solve gibt es nun eine Aktion von Microsoft bei der bis zum 8. Oktober 5000 Exemplare von Visual Studio 2005 Standard Edition verschenkt werden. Zudem gibt es 6 Monate kostenloses Hosting mit ASP.NET 2.0, SQL Server und eine eigene Subdomain bei www.centron.de.

Um in den Genuss dieses Angebots zu kommen muss man sich lediglich fünf CodeClips anschauen und die WebCodes bei der Bestellung eines Developer-Pakets angeben.

Monday, August 28, 2006

BackgroundWorker zum Aktualisieren von GUI-Elementen  #

In einem früheren Blog-Eintrag haben wir gezeigt, wie man durch die Verwendung von Delegates und Threads GUI-Komponenten mit Daten aus parallel laufenden Arbeitsprozessen aktualisieren kann. In .NET 2.0 gibt es dafür ein vorgefertiges Pattern, dass die Lösung für dieses Problem etwas leichter macht. Die notwendige Klasse heißt BackgroundWorker und befindet sich im Namespace System.ComponentModel.

Die Verwendung eines EventHandlers (oder eines Delegates) ist bei einem Programm mit mehreren Threads und grafischer Benutzeroberfläche deswegen notwendig, weil Aktualisierungen des GUIs nur in dem Thread durchgeführt werden können, der auch die GUI-Komponenten konstruiert hat (normalerweise der Haupt-Thread eines Programms). Das klassische Anwendungsszenario dafür ist eine ProgressBar, in der der aktuelle Stand einer langwierigen Operation gezeigt werden soll, die in einem separaten Thread abläuft. Die BackgroundWorker-Klasse stellt die notwendigen Elemente dafür bereit. Die folgenden vier Zeilen definieren ein neues Objekt dieser Klasse, registrieren die Event-Handler und starten den Arbeitsprozess.

 BackgroundWorker bw = new BackgroundWorker();
 bw.DoWork += new DoWorkEventHandler(bw_DoWork);
 bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
 bw.RunWorkerAsync();

In der BackgroundWorker-Klasse sind u.a. zwei Events definiert:
  • DoWork: Hier werden die Funktionen registriert, die die eigentliche Arbeit ausführen, z.B. ein längerer Download, Lesen der Daten von einem SerialPort, usw. Das Delegate hat zwei Parameter: ein Sender vom Typ Object (dies ist das BackgroundWorker-Objekt) und DoWorkEventArgs, über die man weitere Parameter an die Arbeitsfunktion senden kann.
  • ProgressChanged: Diese Event-Handler werden aufgerufen, wenn der Arbeitsprozess eine Änderung gemeldet hat. Dafür muss der Arbeitsprozess die Methode ReportProgress des BackgroundWorker-Objekts aufrufen. Im Event-Handler wird dann die GUI-Elemente aktualisiert.
Die Methode RunWorkerAsync() startet den Arbeitsprozess des BackgroundWorkers. Um das Beispiel zu vervollständigen müssen noch die Methoden bw_DoWork und bw_ProgressChanged definiert werden:

 void bw_DoWork(object sender, DoWorkEventArgs e) {
   BackgroundWorker worker = sender as BackgroundWorker;
   while(...) {
     // do the work ...
     // notify GUI about change
     backgroundWorker.WorkerReportsProgress = true;
     backgroundWorker.ReportProgress(percentage,userState); 
   }
 }

 void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) {
   progressBar.Value=e.ProgressPercentage;
   // Weitere Infos über e.UserState
 }

In der Methode bw_DoWork ist der Aufruf von ReportProgress entscheidend, hier wird der GUI-Thread über eine Änderung des Status informiert, die dann letztlich in bw_ProgressChanged durchgeführt wird. Standardmäßig kann man bei ReportProgress einen Integer-Wert angeben, der den Fortschritt des Prozesses angibt. Wenn man komplexere Informationen an das GUI weiterleiten will, kann man dies über den UserState tun, der ein beliebiges Objekt sein kann. Der UserState kann über eine Property der ProgressChangedEventArgs im Event-Handler abgefragt werden.

Signierung eines Assemblies ohne Visual Studio  #

Mit dem Beitrag vom 22.08. „Signierung eines Assemblies mit dem Visual Studio 2005“ wurde gezeigt, wie Assemblies mit dem Visual Studio 2005 signiert werden können. Die Signierung von Assemblies ist eine notwendige Voraussetzung, um diese als Shared Assemblies in den Global Assembly Cache (GAC) installieren zu können, damit diese systemweit von allen .NET-Applikationen eingebunden werden können.

Selbstverständlich können Assemblies aber auch ohne VS 2005 signiert werden. Dazu sind die folgenden zwei Schritte notwendig:

 

  1. Erstellung eines Schlüsselpaares (öffentlicher und privater Schlüssel)
  2. Signierung des Assemblies unter Angabe der Schlüssel-Datei

 1. Erstellung eines Schlüsselpaares

 

Mit dem SDK wird die Anwendung Strong Name Utility mitgeliefert, die einen öffentlichen und einen privaten Schlüssel erstellt und in einer Datei abspeichert. Zur Generierung der beiden Schlüssel mit dieser Anwendung geben Sie als Kommandozeile den folgenden Befehl ein:

sn.exe –k keys.snk

Dies erzeugt im aktuellen Verzeichnis eine Datei keys.snk, die die Schlüssel enthält. Kopieren Sie diese Datei in Ihr Projekt-Stammverzeichnis.

Hinweis: Durch die Kommandozeile sn.exe –p keys.snk pubkey.snk erhalten Sie in der Datei keys.snk das Schlüsselpaar, während die Datei pubkey.snk lediglich den öffentlichen Schlüssel enthält. Dies kann hilfreich sein, falls Sie den öffentlichen Schlüssel einmal separat aus der Hand geben möchten.

 

2. Signieren des Assemblies

Über eine Attributangabe im Quellcode kann das Assembly nun signiert werden:

 

using System;

using System.Reflection;

 

[assembly:AssemblyKeyFile("keys.snk")] //<your keyFile-Name>

 

 

namespace ClassLibrary1

{

    public class MyFirstSharedAssembly

    {

      //some code here

    }

}

Das Attribut AssemblyKeyFile benötigt als Parameter den Pfad zur Datei, in der das Schlüsselpaar gespeichert wurde.

Hinweis: Weitere Informationen zur Erstellung, Installation und Nutzung von Shared Assemblies finden Sie auch in dem HowTo-Dokument „Erstellung und Installation eines Shared Assemblies“. Dieses Dokument ist nur für angemeldete Nutzer verfügbar. Nutzen Sie unser Anmeldeformular, um  sich kostenlos anzumelden. Sie haben dann uneingeschränkten Zugriff auf alle Dokumente und Beispielanwendungen aus unserem Downloadbereich!

 

Friday, August 25, 2006

C#-FAQ: Bestimmung eines Initialwerts zur iterativen Berechnung von Maximal- und Minimalwerten  #

Bei der Programmierung stellt die iterative Berechnung von Minimal- oder Maximalwerten einer Liste, die in einer Schleife prozessiert wird, einen typischen Anwendungsfall dar. Dabei wird häufig mit folgender if-Abfrage entschieden, ob ein aktuell prozessierter Listenwert größer/kleiner als der gegenwärtige Max/Min-Wert ist:

 

if (actValue > maxValue) maxValue = actValue; //bei Maximalwert-Bestimmung

if (actValue < minValue) minValue = actValue; //bei Minimalwert-Bestimmung

 

Nun stellt sich die Frage, mit welchem Wert man maxValue /minValue idealerweise beim Start der Schleife initialisiert? Das Problem dabei ist, dass bei zu großer (bei einer Minimalwert-Berechnung) oder zu kleiner (bei einer Maximalwert-Berechnung) Initialisierung ein falscher Wert bestimmt wird.

Schaut man sich z.B. die Ermittlung eines maximalen Werts aus einer Liste von Integer-Werten an, muss man maxValue so initialisieren, dass mind. ein Wert der Liste größer ist (nämlich mindestens der maximale Wert der Liste). Analog gestaltet sich das Problem bei der Berechnung eines minimalen Werts. Im Rahmen der Maximalwert-Bestimmung muss man demnach den kleinst möglichen Zahlenwert als Initialwert wählen.

 

Die Lösung dieser Aufgabe ist denkbar simpel: man nutzt die Konstante MaxValue bzw. MinValue der Integer-Datentypen. Möchte man z.B. den maximalen Wert einer Liste mit Int32-Werten bestimmen, initialisiert man maxValue mit

 

int maxValue = Int32.MinValue;

 

So muss mindestens ein Wert in der Liste exisitieren, der größer ist als der initiale maxValue-Wert (es sei denn, alle Werte der Liste entsprechen dem Initialwert, dann ist der Maximalwert dennoch korrekt bestimmt). Analog kann man z.B. auch die Kontante Int64.MinValue oder Double.MinValue  für einen entsprechenden Anwendungsfall nutzen. Für die Berechnung des Minimalwerts einer Int32-Liste gilt analog:

 

int minValue = Int32.MaxValue;

Wednesday, August 23, 2006

Neues HowTo-Dokument zur Erzeugung, Installation und Verwendung von Shared Assemblies zum Download  #

Ab sofort ist das HowTo-Dokument „Erstellung und Installation eines Shared Assemblies“ im Downloadbereich verfügbar.

Dieses Dokument beschreibt, wie Shared Assemblies (auch als Public Assemblies bekannt) erstellt, in den Global Assembly Cache (GAC) installiert und anschließend von anderen Assemblies referenziert werden können.

 

Dieses Dokument ist nur für angemeldete Nutzer verfügbar. Nutzen Sie unser Anmeldeformular, um  sich kostenlos anzumelden. Sie haben damit uneingeschränkten Zugriff auf alle Dokumente und Beispielanwendungen aus unserem Downloadbereich!

 

Tuesday, August 22, 2006

Signierung eines Assemblies mit dem Visual Studio 2005  #

Zur Signierung eines Assemblies mit dem Visual Studio 2005 sind die folgenden zwei Schritte notwendig:

 

  1. Erstellung eines Schlüsselpaares (öffentlicher und privater Schlüssel)
  2. Signierung des Assemblies unter Angabe der Schlüssel-Datei

 1. Erstellung eines Schlüsselpaares

 

Um mit dem VS 2005 ein Schlüsselpaar zu erstellen, öffnen Sie das Projekt-Eigenschaftsfenster über die Menüfolge „Project“ -> „<Your ProjectName> Properties“. Es öffnet sich das Eigenschaftsfenster des aktuellen Projekts. Wechseln Sie zur Registerkarte „Signing“ und aktivieren Sie die Checkbox „Sign the assembly“. Wählen Sie nun den Eintrag „<New>“ aus der Auswahlbox. Es öffnet sich ein Dialog-Fenster zur Eingabe eines geeigneten Dateinamens, in dem das Schlüsselpaar gespeichert werden soll. Optional können Sie Ihr Schlüsselpaar mit Login und Passwort sichern. Bestätigen Sie Ihre Eingaben mit dem Schaltknopf „OK“. Ihr Schlüsselpaar wird nun generiert und in der angegebenen Datei gespeichert.

 

2. Signierung des Assemblies

 

Um mit dem VS 2005 ein Assembly unter Angabe einer Schlüsseldatei zu signieren, öffnen Sie das Projekt-Eigenschaftsfenster wie unter 1. beschrieben. Wechseln Sie zur Registerkarte „Signing“ und aktivieren Sie die Checkbox „Sign the assembly“.

Wählen Sie nun aus der Auswahlbox den Punkt „<Browse>“ (oder alternativ die Schlüsseldatei, falls Sie den ersten Schritt ausgeführt haben und diese damit direkt gelistet sein sollte) und wählen Sie Ihre Schlüsseldatei über den Dateiauswahl-Dialog.

 

Beim nächsten Kompiliervorgang wird das Assembly automatisch mit dem spezifizierten Schlüssel signiert. Die digitale Signatur wird in das Manifest des Assemblies eingetragen.  Die Signierung des Assemblies ist eine notwendige Voraussetzung, um als Shared Assembly in den Global Assembly Cache (GAC) installiert zu werden. Daneben haben Shared Assemblies u.a. die folgenden Vorteile:

 

-          aufgrund der Signierung und des öffentlichen Schlüssels ist eine Authentifizierung vor der Ausführung durch die CLR möglich

-          durch die Angabe einer Versionsnummer kann das Vorhandensein einer exakt definierten Assembly-Version vor der Ausführung erzwungen werden.

-          durch die Verwendung der Versionsnummer als Bestandteil der Assembly-Identität können im GAC gleichzeitig mehrere Versionen desgleichen Assemblies installiert und von anderen Anwendungen genutzt werden

 

Hinweis: alle Angaben zu Visual Studio 2005 beziehen sich auf die englischsprachige Version 8.0.50727.42

 

Monday, August 21, 2006

Eigene Attribute definieren  #

Wie im Blog-Eintrag vom 14.08.2006 erwähnt, kann man eigene Attribute definieren.

Zuerst erstellt man eine Klasse die von System.Attribute abgeleitet ist. Es ist eine gängige Praxis, eigene Attribut-Klassen als sealed zu markieren. Alle Attributklassen haben als Suffix "Attribute".

public sealed class UserDescriptionAttribute : System.Attribute {

private String _description;

public UserDescriptionAttribute(String description) {
_description = description;
}
public UserDescriptionAttribute() { }

public String description() {
get { return _description; }
set {_description = value; }
}

}

Beim Anwenden des neuen Attributes hat man die Möglichkeit, den kompletten Namen anzugeben (inklusive Suffix "Attribute") oder die Kurzform.

[UserDescriptionAttribute("Alle Schueler gehen in eine Klasse")]
public class Schueler{

// ...

}

[UserDescription("Alle Lehrer unterrichten eine oder mehrere Klassen")]
public class Lehrer {

// ...

}

Man kann die Verwendung von eigenen Attributen einschränken. Dazu gibt es das Attribut [AttributeUsage] und man kann folgende Werte benutzen:

public enum AttributeTargets {

All, Assembly, Class, Constructor, Delegate, Enum, Event, Field,
Interface, Method, Module, Parameter, Property, ReturnValue, Struct

}

Wenn wir definieren möchten, dass unser eigenes Attribut nur in Classen und Assemblies benutzt werden soll, sieht die Klasse folgendermassen aus:

[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class)]
public sealed class UserDescriptionAttribute : System.Attribute {

private String _description;

public UserDescriptionAttribute(String description) {
_description = description;
}
public UserDescriptionAttribute() { }

public String description() {
get { return _description; }
set {_description = value; }
}

}

Es empfiehlt sich, die Einschränkung für die Benutzung der eigenen Attribute immer mit anzugeben.

Friday, August 18, 2006

Komponentenbasierte Architektur: benutzerdefinierte Metadaten in C#  #

Komponentenbasierte Softwarearchitekturen basieren auf dem Prinzip, Applikationen aus mehreren, a priori autonomen (kontextfreien) Einheiten zu komponieren, die untereinander Informationen/Daten austauschen und definierte Teilaufgaben erledigen.

Mitunter kommt eine Kooperation dieser Einzel-Komponenten ad hoc zustande, d.h. die Ermittlung einer für ein bestimmtes Arbeitspaket geeigneten Komponente und anschließende Aufgabenverteilung wird erst zur Laufzeit entschieden. Damit eine solche Arbeitsorganisation effektiv gestaltet werden kann, benötigen die einzelnen Komponenten gegenseitige Informationen (z.B. welche Funktionalitäten von einzelnen Komponenten zur Verfügung gestellt werden, wie Schnittstellen verfügbarer Komponenten gestaltet sind oder welche Integritätsbedingungen für ein Zusammenwirken erfüllt sein müssen).

.NET stellt mit dem Konzept der Assembly-Metadaten, die zur Laufzeit über Reflektion ermittelt werden können, eine geeignete Möglichkeit zur Verfügung, solche deskriptiven Komponenten-Informationen zu verwalten.

Neben den automatisch durch den Sprachcompiler generierten Metadaten (Informationen über Methoden, Eigenschaftslisten, Eigenschaftswerte etc.) können auch benutzerdefinierte Metadaten gespeichert werden.

Das folgende Listing zeigt, wie durch die Definition eigener Attributklassen im Grunde beliebige, selbst definierte Metadaten als Komponenten-Information gespeichert werden können.

 

[System.AttributeUsage(System.AttributeTargets.Class)]

 

public class InputParameterDefinition : System.Attribute

{

    public string imageType;

    public int maxImages;

 

    public InputParameterDefinition(string imageType)

    {

        this.imageType = imageType;

        maxImages = 2;

    }

}

 

Die Angabe [System.AttributeUsage(System.AttributeTargets.Class)]beschränkt die Verwendung dieser Attributklasse auf Klassen. Das definierte Attribut heißt InputParameterDefinition und kann über diesen Namen in anderen Klassen referenziert werden. Diese Attributklasse hat einen positionalen (imageType) und einen benannten (maxImages) Parameter. Während positionale Parameter als Eingabeparameter des Attribut-Konstruktors obligatorisch sind, sind benannte Parameter optional.

Diese Attributklasse beschreibt im exemplarischen Kontext einer kompositionalen Bildanalyse-Applikation die Definition eines Eingabeparameter-Typs (imageType) und die Anzahl der maximal parallel zu prozessierenden Eingabe-Bilder.

 

Diese neue Attributklasse kann nun wie folgt genutzt werden:

 

[InputParameterDefinition("tiff", maxImages = 2)]

 

    public class ImageAnalysis

    {

        public ImageAnalysis()

        {

            //some code

        }

    }

 

Durch die Angabe [InputParameterDefinition("tiff", maxImages = 2)] wird definiert, dass die Klasse ImageAnalysis nur Bilder des Typs „TIFF“ und maximale 2 parallel zu verarbeitende Bilder als Eingabeparameter entgegennimmt. Diese Informationen werden automatisch als Metadaten im ImageAnalysis-Assembly abgespeichert.

 

Zur Laufzeit kann dieses Attribut dann z.B. wie folgt ausgelesen werden:

 

Attribute[] attributes = System.Attribute.GetCustomAttributes(typeof(ImageAnalysis));

foreach (InputParameterDefinition pd in attributes) {

      if (pd != null)

      {

            Console.WriteLine("ImageType: " + pd.imageType);

            Console.WriteLine("MaxNrOfImages: " + pd.maxImages);

      }

 }

 

Falls die Attribute zur Entwurfszeit bekannt sind, lässt sich das hier präsentierte Beispiel auch mit Getter- und Setter-Methoden lösen. Häufig allerdings sind diese Definitionen a priori nicht bekannt oder ändern sich im Laufe der Zeit; für solche Szenarien eignen sich Attributklassen, um z.B. eine Liste zur Entwurfszeit unbekannter Attribute zu iterieren.

 

Thursday, August 17, 2006

C#-FAQ: Formatierung numerischer Werte  #

Um numerische Werte in C# als Zeichenketten zu formatieren, werden Standardformatbezeichner und die Methoden string.Format() oder object.ToString() genutzt. Für den Fall, dass die Standardformatbezeichner für die vorgesehenen Zwecke nicht ausreichen, können benutzerdefinierte Formatzeichenfolgen definiert werden, um das gewünschte Format zu ermöglichen. Dieser Beitrag beschäftigt sich mit drei typischen Formatierungsanforderungen:

 

  1. Begrenzung von Dezimalstellen
  2. Tausendertrennzeichen
  3. Exponential-Schreibweise

1. Begrenzung von Dezimalstellen

Um die Anzahl der Dezimalstellen einer Fließkommazahl zu begrenzen, kann der Standardformatbezeichner F genutzt werden. Dazu wird die gewünschte Anzahl der Nachkommastellen dem Bezeichner F als Suffix hinzugefügt. Das folgende Listing zeigt, wie die Anzeige eines Double-Werts auf zwei Nachkommastellen begrenzt werden kann.

 

double myDouble = 12.129;

Console.WriteLine(myDouble.ToString("F2"));

 

Die Ausgabe des myDouble-Werts lautet 12,13. Bei der Formatierung dieser Ausgabenzeichenfolge wird automatisch auf die zweite Nachkommastelle gerundet.

 

Die im Listing dargestellte Formatierungsanweisung F2 begrenzt die Ausgabe auf zwei Dezimalstellen. Falls die zu formatierende Zahl jedoch keine Nachkommastellen hat, wird die Anzahl der gewünschten Nachkommastellen mit Nullen aufgefüllt. D.h., dass z.B. die Zahl 1202 mit der Formatangabe F2 zu 1202,00 formatiert wird.

Falls dies nicht gewünscht ist, kann man eine benutzerdefinierte Formatzeichenfolge folgendermaßen definieren: 0.##. Diese Formatzeichenfolge bewirkt, dass maximal zwei Nachkommastellen dargestellt werden. Die Angabe des Rautenzeichens bedeutet hier eine optionale Darstellung der Nachkommastellen. Das folgende Listing zeigt den Einsatz der benutzerdefinierten Formatzeichenfolge:

 

double myDouble1 = 12.129;

Console.WriteLine(myDouble1.ToString("0.##"));

double myDouble2 = 1202;

Console.WriteLine(myDouble2.ToString("0.##"));

 

Die Ausgabe des myDouble1-Werts lautet 12,13,  während die zweite Ausgabe 1202 lautet.

 

2. Tausendertrennzeichen

Ein weiterer häufiger Formatierungswunsch ist die Anzeige von Tausendertrennzeichen (ein Punkt nach jeder dritten Stelle vor dem Komma). Diese Formatierung kann in C# recht komfortabel durch den Standardformatbezeichner N erreicht werden. Dabei kann analog zum Formatbezeichner F die Anzahl der darzustellenden Nachkommazahlen als Suffix angegeben werden.

Das folgende Listing zeigt einen möglichen Einsatz des Formatbezeichners N:

 

double myDouble1 = 123456;

Console.WriteLine(myDouble1.ToString("N2"));

double myDouble2 = 123456.457;

Console.WriteLine(myDouble2.ToString("N2"));

 

Die Ausgabe im ersten Fall lautet 123.456,00. Im zweiten Fall lautet die Ausgabe 123.456,46.

 

3. Exponential-Schreibweise

Um eine Zahl in Exponential-Schreibweise darzustellen (etwa weil die Zahl sehr groß bzw. sehr klein ist), kann man den Standardformatbezeichner E verwenden. Das folgende Listing zeigt zwei Beispiele, die in Exponential-Schreibweise formatiert werden:

 

double myDouble1 = 0.00001234;

Console.WriteLine(myDouble1.ToString("E"));

double myDouble2 = 1234456.34;

Console.WriteLine(myDouble2.ToString("E"));

 

Die erste Ausgabe lautet 1,234000E-005, die zweite 1,234456E+006. Der Exponent besteht aus einem Plus- oder Minuszeichen und mindestens drei Ziffern. Ggf. wird der Exponent durch Nullen ergänzt, um diesem Mindestwert zu entsprechen.

 

Hinweis: Die Ausgabe der Ergebniszeichenfolge wird von den Ländereinstellungen der Systemsteuerung beeinflusst. Die hier dargestellten Beispiele sind gültig für eine deutsche Ländereinstellung.

Auf den MSDN-Seiten findet sich eine detaillierte Übersicht der Standardformatbezeichner.

 

Monday, August 14, 2006

Attribute in .NET  #

Attribute sind eine Möglichkeit, zusätzliche Metadaten einer Assembly hinzuzufügen. Ein Beispiel für ein solches Attribut ist [Serializable]. So könnte ein Code-Ausschnitt aussehen:

[Serializable]
public class Adresse {

String vorname;
String nachname;

...
}

Durch Hinzufügen des Attributes [Serializable] ist es jetzt möglich, Objekte dieser Klasse bspw. in eine Datei abzuspeichern und zu einem späteren Zeitpunkt wieder einzulesen, ohne dass man eigenen Code programmieren muss.

Ein anderes nützliches Attribut ist [Obsolete]. Hier ein Beispiel:

[Obsolete, "Diese Klasse ist veraltet, bitte benutzen Sie stattdessen die Klasse Transporter"]
public class Bus {

int leistungKW;
String ziel;

...
}

Der C#-Compiler überprüft, ob die obsolete Klasse verwendet wird. Beim Kompilieren führt diese Anweisung zu einem Fehler:

Bus b = new Bus();

Im Ausgabefenster erscheint der Text, den wir im Attribut spezifiziert haben.

Hier noch die wichtigen Punkte zu Attributen:

  • Attribute sind Klassen die von System.Attribute abgeleitet sind.
  • Attribute fügen zusätzliche Metadaten der Assembly hinzu.
  • Attribute müssen von anderen Komponenten interpretiert (z.B. C#-Kompiler bei [Obsolete]) werden, ansonsten haben sie keinen Effekt.

Man kann auch eigene Attribute spezifizieren, dies wird demnächst erklärt.

Wednesday, August 02, 2006

Erstes HowTo Dokument zur Serverseitigen Bilderzeugung  #

Das erste HowTo Dokument aus der Serie zur serverseitigen Bilderzeugung ist im Download-Bereich verfügbar.
Es beschreibt die Grundlagen um dynamisch Grafiken zu erzeugen, die auf Webseiten dargestellt werden sollen. Es wird eine einfache Web-Applikation erstellt, die ein Textfeld enthält. Der Text, den ein Benutzer eingibt, wird in eine Grafik umgewandelt und als Bild in der Selben Seite angezeigt.

Monday, July 31, 2006

Was ist 'boxing' und 'unboxing' und wieso man es möglichst vermeiden soll?  #

In .NET gibt es Wertetypen und Referenztypen (siehe Blog-Eintrag "Struct oder doch lieber Klasse?"). Aber was soll passieren, wenn man einem Refernztypen den Wert eines Wertetypen zuweisen möchte?

Mit 'Boxing' versteht man die Umwandlung eines Wertetyps in einen Referenztypen und 'Unboxing' logischerweise die Umwandlung eines Referenztyps in einen Wertetyp.

Wozu ist das gut und wie "mache" ich 'Boxing'/'Unboxing'?

Schauen wir uns folgenden Code an:

ArrayList numbers = new ArrayList();

int i = 42;
numbers.Add(i);

float f = 42f;
numbers.Add(f);

Dies kompiliert prima und auch bei der Ausführung läuft alles wie geplant. Beim Aufruf von "numbers.Add(i)" wird automatisch ein 'Boxing' durchgeführt, da Wertetypen nicht in einer ArrayList gespeichert werden können sondern nur Referenztypen, die von System.Object abgeleitet sind.

Hier sieht man auch das große Problem: 'Boxing'/'Unboxing' geschieht automatisch ohne dass man etwas machen muss. Dies verleitet zu der obigen unsauberen Programmierung mit den entsprechenden Performanznachteilen, die eine automatische Umwandlung mit sich bringt.

Entsprechend wird hier ein automatisches 'Unboxing' gemacht:

int i2 = (int)numbers[0];

In .NET 2.0 wird 'Boxing'/'Unboxing' durch die Einführung von "Generics" verhindert. Durch den folgenden Code können zur Liste nur Font-Objekte hinzugefügt werden, so dass 'Boxing'/'Unboxing' unnötig ist:

List<Font> fonts = new List<Font>();

Friday, July 28, 2006

Struct oder doch lieber Klasse?  #

Häufig werde ich gefragt, ob es „objektive“ Kriterien gibt, die eine Favorisierung von Structs gegenüber Klassen begründen.

Bislang habe ich auf die Frage nach einer Entscheidung zwischen Structs und Klassen geantwortet, dass dies von den genauen Umständen abhängt (also welche Aufgaben der zu implementierende Typ übernehmen soll).

Aber um die Antwort auf diese Frage zu verstehen, sollte man sich zu aller erst den wesentlichen Unterschied zwischen einer Struktur und einer Klasse verdeutlichen: während Klassen in C# (genau wie in allen anderen .NET-Sprachen) einen Referenztypen darstellen, die im Speicher auf dem Heap verwaltet werden, sind Structs Wertetypen, die auf dem Stack verwaltet werden. In C# werden primitive Datentypen wie z.B. Zahlenwerte als Wertetypen auf dem Stack verwaltet. Dies bedeutet, dass diese die Daten direkt enthalten, während Referenztypen lediglich einen Verweis auf die Daten enthalten. Da bei der Speicherung von Wertetypen keine weiteren Speicherreferenzen benötigt werden, können Strukturinstanzen im Allgemeinen ressourcenschonender als Klasseninstanzen eingesetzt werden.

 

Im operativen Einsatz macht sich die Unterscheidung zwischen Referenz- und Wertetypen u.a. bei einer Zuweisung (etwa beim Kopieren von Objekten) bemerkbar:

weist man einer Stuct-Variable A eine zweite Struct-Variable B zu, werden alle der Variablen B inhärenten Daten dupliziert und als Variable A auf dem Stack abgelegt (diese Daten existieren dann doppelt im Speicher). Weist man hingegen einer Klassen-Variable A eine zweite Klassen-Variable B zu, wird auf dem Stack lediglich eine zweite Referenz angelegt, die auf die gleiche Stelle im Heap zeigt wie die Variable B (in diesem Fall werden die Daten also nicht dupliziert, sondern existieren nur einmal im Speicher!). In diesem Fall würden Änderungen an den Heap-Daten beide Referenzen (A und B) auf dem Stack beeinflussen.

Die Unterscheidung von Referenz- und Wertetypen bedingt den weitereren Unterschied, dass einige der klassischen objektorientierten Konzepte wie z.B. Vererbung von Structs nicht unterstützt werden.

 

Nun aber wieder zurück zu der Frage nach den Kriterien zur Strategieauswahl: das MSDN hat in einem Artikel Struct Usage Guidelines“ die folgenden Punkte aufgeführt, wann Typen als Strukturen implementiert werden sollten (sinngemäß übersetzt):

  • sie agieren wie primitive Datentypen
  • ihre Instanzgröße liegt unter 16 bytes
  • sie sind unveränderlich
  • eine Wertetypsemantik ist erwünscht

Vor der Entscheidung, einen Typen als Struktur zu implementieren, sollte daneben auch bedacht werden, dass Structs natürlich nur als Werte einer Methode als Parameter übergeben werden können und nicht als Referenzen. Insbesondere bei häufigen Parameterübergaben sollte demnach aus Performance-Gründen eine Klassen-Implementierung favorisiert werden.

Monday, July 24, 2006

Unterschied zwischen 'readonly' und 'const'  #

Auf den ersten Blick sehen die beiden Ausdrücke aus, als ob sie das ähnliche wenn nicht sogar das gleiche bewirken. Dem ist aber nicht so, es gibt kleine aber feine Unterschiede!

Unterschied 1: Ein beliebiger Typ kann 'readonly' gesetzt werden!

Folgendes Statement wird reibungslos kompilieren:

protected readonly Font readonlyFont = new Font("Arial", 12.0f);

Wohingehend hier ein Fehler auftritt:

protected const Font constFont = new Font("Arial", 12.0f);

'const' ist nur zulässig für primitive Datentypen, enums und Strings. 'readonly' ist universell einsetzbar.

Unterschied 2: 'const' ist "gefährlich" wenn man Librarys in Form von DLLs erstellt.

Das wird dadurch verursacht, wie der Compiler 'readonly' und 'const'-Typen behandelt.

'readonly'-Typen werden mit Namen und Wert in dem Assembly abgelegt, aber es ist nicht möglich, dass der Wert programm-technisch verändert wird.

'const'-Typen werden zur Kompilierzeit durch den Wert ersetzt! D.h. folgende beiden Varianten ergeben dasselbe Kompilat:

Variante 1:

protected const String helloWorld = "Hello World";

public void printHelloWorld() {
   Console.Out.WriteLine(helloWorld);
}

Variante 2:

public void printHelloWorld() {
   Console.Out.WriteLine("Hello World");
}

Und jetzt wird auch offensichtlich, wieso 'const' in DLLs "gefährlich" sind. Wenn ein Programmierer den Unterschied nicht kennt und ein Programm aus mehreren Assemblys zusammensetzt, werden in allen verwendeten Assemblys die konstanten Werte in die IL eingefügt. Ändert man den Wert und ersetzt eine von mehreren alten Assemblys durch eine neu-kompilierte, verwendet nur die neue Assembly den neuen Wert, die anderen Assemblys beinhalten ja noch den alten Wert!!

Dies kann nicht passieren bei der Verwendung von 'readonly', da dort immer eine Referenz auf die Definition gespeichert wird und somit überall derselbe Wert verwendet wird.

Friday, July 21, 2006

Formel-Analyse durch reguläre Ausdrücke in C#  #

In einem aktuellen Software-Projekt haben wir uns mit einer interessanten Aufgabenstellung beschäftigt, die so oder in ähnlicher Form mit Sicherheit dem ein oder anderen bekannt vorkommen dürfte: Parsen von benutzerdefinierten Formeln nach einer deklarierten Syntax.

Die zu analysierenden Formeln waren wie folgt aufgebaut:

function1(param1,function2(param1,param2),param3)

Jede Funktion der Formel besteht aus einem Keyword (im Beispiel function1 und function2), das die eigentliche Funktion identifiziert. Eine durch Kommata getrennte Parameterliste der Funktion wird anschließend in einem Klammerausdruck angegeben. Die Funktionen können natürlich beliebig geschachtelt sein.

Die Aufgabenstellung bestand nun darin, die einzelnen Funktionen aus der Gesamtformel zu filtern um diese dann anschließend zu berechnen.

Reguläre Ausdrücke bieten sich an, ein solches Problem zu lösen.

.NET stellt im Namespace System.Text für die Arbeit mit regulären Ausdrücken die Klassen Regex zur Verfügung.

Eine erfolgreiche Strategie, um die geschachtelten Funktionen aufzulösen, besteht nun darin, nach beliebigen Funktionen zu suchen, die selbst keine anderen Funktionen mehr als Parameter besitzen (eine solche Funktion muss in der Formel existieren. Eine andere Strategie könnte z.B. zuerst die „innerste“ Funktion finden und berechnen).

Dazu lässt sich der folgende reguläre Ausdruck definieren, mit dem die gesamte Formel geparst wird:

 

Regex regex = new Regex("(function1|function2)[(][^(^)]*[)]");

 

Der erste Teil dieses regulären Ausdrucks definiert eine Liste mit Keywords von Funktionen, die bekannt sind und später berechnet werden sollen. Der zweite Teil sucht nach Klammerausdrücken, die selbst keine öffnenden und schließenden Klammern beinhalten.

Das folgende C#-Schnipsel zeigt, wie man solche Funktionen filtern kann:

 

using System.Text.RegularExpressions;

….

string s = "function1(param1,function2(param1,param2),param3)";

Regex regex = new Regex("(function1|function2)[(][^(^)]*[)]");

MatchCollection mc = regex.Matches(s);

for (int i=0; i < mc.Count; i++){

   Console.WriteLine("Funktion an Pos.: " + mc[i].Index);

   Console.WriteLine("Funktion: " + mc[i].Value);

   computeValueOfFunction(mc[i].Value);

  }

 

Im Beispiel liefert mc[0].Value z.B. function2(param1,param2).

Hat man erst einmal eine Funktion identifiziert, kann man diese nach der Ermittlung ihrer Parameter (die durch Kommata getrennt sind und zwischen den Klammern stehen) und des eigentlichen Funktions-Keywords (der linke Teil vor der öffnenden Klammer) berechnen (im Beispiel angedeutet durch computeValueOfFunction(). Anschließend wird diese Funktion in der Formel durch ihr Ergebnis ersetzt und die so modifizierte Formel erneut geparst. Dies wird solange wiederholt, bis alle Funktionen berechnet wurden und die verbleibende Formel-Zeichenkette das Gesamtergebnis des Ausdrucks darstellt.

Wednesday, July 05, 2006

Neues Whitepaper online: das evidenzbasierte .NET Sicherheits-Konzept (CAS)  #

Das .NET-Framework erweitert das rollenbasierte Sicherheits-Konzept (so wie es z.B. bei vielen Betriebssystemen zum Einsatz kommt) um einen weiteren, beweislastorientierten Ansatz. Dieser neue Ansatz sammelt zur Laufzeit Informationen rund um die auszuführende Anwendung (z.B. ihre Herkunft) und übergibt der Anwendung dann auf der Grundlage dieser gesammelten Informationen und den Sicherheitseinstellungen des Systems die benötigten Rechte oder verweigert die Vergabe.

Dieses Whitepaper erläutert das Sicherheitskonzept des .NET-Frameworks und zeigt, wie und in welchem Umfang die Sicherheitseinstellungen konfiguriert werden können und worauf bei der Entwicklung eines Assemblies in diesem Zusammenhang zu achten ist, um böse Überraschungen bei der Ausführung zu vermeiden.

Win32-Systemaufrufe in .NET Teil 2: Fehlercode ermitteln  #

Dieser Beitrag ist eine Ergänzung zum Beitrag vom 29.06.06 „Win32-Systemaufrufe in .NET“, in dem ich gezeigt habe, wie .NET-Assemblies nicht verwaltete Funktionen sehr einfach über PInvoke (am Beispiel eines Win32-API-Aufrufs über das Attribut DLLImport) aufrufen können.

Ein weiterer interessanter Punkt, den ich in diesem Beitrag offen gelassen habe, ist die Frage, wie man auf Fehler, die eine solche nicht verwaltete Funktion möglicherweise erzeugt, reagieren kann. Eine erste, vielleicht nahe liegende Idee, einen potentiellen Fehler in einem try…catch-Block zu behandeln, wird erfolglos bleiben, da dieses Konstrukt nur verwaltete Fehler behandelt.

Das DLLImport-Attribut verfügt aber über einen Parameter SetLastError, der in diesem Fall helfen kann. Wird dieser Parameter auf true gesetzt, kann der Code des Fehlers, der von der unverwalteten WIN32-API-Funktion erzeugt wird, über die statische Methode Marshal.GetLastWin32Error() ermittelt werden. Betrachten wir das Beispiel-Fragment des letzten Beitrags und erweitern es um die hier erläuterten Möglichkeiten, erhalten wir folgendes Codeschnipsel:

 

using System.Runtime.InteropServices;

...

    class APICall

    {

        [DllImport("kernel32.dll", SetLastError= true)]

       

        static extern uint WinExec(string command, uint uCmdShow);

 

        public void callWinAPI(string file)

        {

            WinExec("Notepad.exe " + file, 1);

            int errorCode = Marshal.GetLastWin32Error();

            Console.WriteLine("Fehlercode: " + errorCode);

         }

    }

 

Um die Wirksamkeit der Fehlercode-Ermittlung zu prüfen, können wir der WinExec-Funktion nun einen Anwendungspfad oder -namen übergeben, der nicht existiert (z.B. „Notepads.exe“). Dies wird einen Fehler erzeugen, der als „errorCode“ gespeichert wird. Im Folgenden kann dann in Abhängigkeit des Fehlercodes eine Ausnahmebehandlung stattfinden.

Die nicht verwaltete Funktion FormatMessage aus der kernel32.dll liefert übrigens eine Textbeschreibung der entsprechenden Fehlercodes.

Eine detaillierte Übersicht der DLLImport-Attribute wird auf den MSDN-Seiten dargestellt.

 

Thursday, June 29, 2006

Win32-Systemaufrufe in .NET  #

In unserer letzten Schulung ist unter anderem die Frage aufgekommen, wie und ob das .NET-Framework Kompatibilität zu Anwendungen gewährleistet, die aus Zeiten vor der .NET-Ära stammen. Da dieses Thema für viele von zentralem Interesse scheint, möchte ich mit diesem Beitrag am Beispiel eines Win32 API Aufrufs eine einfache Möglichkeit aufzeigen, wie .NET-Anwendungen „unmanaged Code“ in DLL-Bibliotheken aufrufen können.

 

using System.Runtime.InteropServices;

...

    class APICall

    {

        [DllImport("kernel32.dll")]

       

        static extern uint WinExec(string command, uint uCmdShow);

 

        public void callWinAPI(string file)

        {

            WinExec("Notepad.exe " + file, 1);

         }

    }

 

Der Mechanismus, der hier zum Tragen kommt, ist im .NET-Framework als Platform Invocation (oder kurz: PInvoke) bekannt. Das oben dargestellte Code-Schnipsel ruft den Texteditor Notepad über die API-.Funktion WinExec auf. Dieser Funktion wird als Parameter der Name / Pfad der auszuführenden Anwendung übergeben. Mit dem zweiten Parameter des Aufrufs kann die Art und Weise gesteuert werden, wie das Fenster angezeigt werden soll (übergibt man z.B. den Wert „3“, wird das Fenster im Vollbildmodus angezeigt).

Um PInvoke zu nutzen, muss man die Klassen im Namespace System.Runtime.InteropServices importieren. Zum Zweiten muss die DLL, in der die aufzurufende Funktion implementiert ist, über das Attribut DllImport eingebunden werden. Die hier verwendete Funktion zum Starten einer Anwendung liegt in kernel32.dll. Schließlich muss im Quellcode eine Methode definiert sein, mit der auf die aufzurufende Funktion zugegriffen werden kann. Die Argumente, die in der Signatur dieser Methode angegeben sind, müssen mit den Argumenten der Zielfunktion übereinstimmen, da sonst ein Laufzeitfehler auftritt. Des Weiteren muss diese Methode als static und extern deklariert sein.

 

Man sollte aber nach Möglichkeit auf Platform Invocation verzichten, falls das .NET-Framework Klassen zur Verfügung stellt, die die gleiche Funktionalität bieten. Z.B. kann man das Ergebnis des oben präsentierten C#-Fragments auch über die .NET-Klasse Process aus dem Namespace System.Diagnostics erreichen:

 

Process.Start("c:\\windows\\notepad.exe", yourFile);

 

Während für viele Win32-API Aufrufe äquivalente .NET-Funktionen verfügbar sind, muss man für den Aufruf selbst entwickelter COM-Objekte häufig auf die Möglichkeit der Platform Invocation zurückgreifen.

Wednesday, June 28, 2006

3D-Text mit Managed DirectX und C# darstellen  #

In einem ersten Tutorial zur Programmierung von Managed DirectX mit C# hatten wir gezeigt, wie man eine grundlegende DirectX-Anwendung erstellen kann. In einer Fortsetzung des Tutorials zeigen wir nun, wie man mit DirectX 3D-Text erzeugen, darstellen und rotieren lassen kann. Der Source-Code für die entwickelte Beispielanwendung ist ebenfalls verfügbar.

Tuesday, June 27, 2006

GUI-Änderungen in Forms und Multi-Threading unter .NET  #

Wie gestern schon im Beitrag 'Delegates in .NET' angekündigt, möchte ich heute auf das Problem mit GUI-Änderungen in Forms und multi-threaded Anwendungen zu sprechen kommen.

Das Beispiel ist eine Anwendung, die über den seriellen Port Daten erhält und diese sollen in einem Label angezeigt werden. Dazu würde man einen Eventhandler definieren, der bei eingehenden Daten über den seriellen Port aufgerufen wird. Dann wird der Inhalt des Labels mit den empfangenen Daten überschrieben. Das könnte so aussehen:

public SerialPort serialPort = new SerialPort("Com1",19200,0,8,1);
private SerialDataReceivedEventHandler serialDataReceivedEventHandler = null;

private System.Windows.Forms.Label lblSerialValue;

public SerialDataClient()
{
    InitializeComponent();
    serialDataReceivedEventHandler = new SerialDataReceivedEventHandler(SerialPortDataReceived);
    // Attach a method to be called when there is data waiting in the port's buffer
    serialPort.DataReceived += serialDataReceivedEventHandler;
}

private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
    // the received bytes
    byte[] data = new byte[serialPort.BytesToRead];
    lblSerialValue.Text = data.ToString();
}

Das Problem bei der Ausführung ist, dass eine Exception geworfen wird, wenn der Inhalt des Labels gesetzt werden soll ("lblSerialValue.Text = data.ToString();"). Dies hängt damit zusammen, dass GUI-Elemente nur von dem Thread verändert werden können, von dem sie erzeugt wurden.

Das Empfangen der seriellen Daten läuft aber in einem anderen Thread ab. Was kann man nun machen? Man benutzt einen Delegate!

public SerialPort serialPort = new SerialPort("Com1",19200,0,8,1);
private SerialDataReceivedEventHandler serialDataReceivedEventHandler = null;

private System.Windows.Forms.Label lblSerialValue;

// the interface update delegate of the main part of the screen
public delegate void HandleInterfaceUpdateDelegate(String aValue);
public HandleInterfaceUpdateDelegate handleInterfaceUpdateDelegate;

public SerialDataClient()
{
    InitializeComponent();
    serialDataReceivedEventHandler = new SerialDataReceivedEventHandler(SerialPortDataReceived);
    // Attach a method to be called when there is data waiting in the port's buffer
    serialPort.DataReceived += serialDataReceivedEventHandler;
    handleInterfaceUpdateDelegate = new HandleInterfaceUpdateDelegate();
}

private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
    // the received bytes
    byte[] data = new byte[serialPort.BytesToRead];
    this.Invoke(handleInterfaceUpdateDelegate, new String[] {data.ToString()});
}

private void UpdateLblSerialValue(String aValue) {
    lblSerialValue.Text = aValue;
}

Mit dem Aufruf "this.Invoke()" veranlasst man den Hauptthread dieses Forms, den Delegate auszuführen und somit wird die Änderung von dem "richtigen" Thread durchgeführt. Nun wird keine Exception mehr geworfen.

Einfache Prüfung auf Spracheninteroperabilität  #

Um sicherzustellen, dass selbst erstellte Software-Komponenten auch tatsächlich in anderen .NET-Sprachen verwendet werden können, ist es notwendig, dass diese Komponenten nur Typen und Konstrukte verwenden, die in der Common Language Specification (CLS) definiert sind. Manchmal ist es aber nicht immer klar, ob ein verwendetes Konstrukt tatsächlich CLS kompatibel ist. Zu diesem Zweck kann das Assembly-Attribut [CLSCompliant(true)] eingesetzt werden, das den C#-Compiler anweist, den Quelltext auf CLS-Kompatibilität zu prüfen.

 

Der C#-Compiler würde z.B. für folgende Klassendefinition einen Hinweis ausgeben, dass die CLS-Kompatibilität nicht gewährleistet ist:

 

using System;

namespace MyTestApplication

{

    [CLSCompliant(true)]

    class NonCLSCompliant

    {

        public uint ComplianceTest(uint a, uint b) { return (a + b); }

    }

}

 

Der Datentyp uint (vorzeichenlose 32-Bit-Ganzzahl) ist zwar im Common Type System (CTS) definiert und kann damit in einigen .NET-Sprachen verwendet (z.B. in C#) und von der Common Language Runtime (CLR) in Maschinencode übersetzt werden, eine Definition in der CLS aber fehlt.

Entwickler, die Komponenten bewusst mit dem Ziel der Wiederverwendung respektive Vererbung in allen .NET-Sprachen implementieren, sollten dieses Assembly-Attribut nutzen, um die geforderte CLS-Kompatibilität sicher zu stellen.

Monday, June 26, 2006

Delegates in .NET  #

Was ist eigentlich ein Delegate?

Ein Delegate ist ein Objekt, welches auf eine Methode zeigt, die dann zu einem späteren Zeitpunkt aufgerufen werden kann. Ein Delegate wird definiert über die Parameter-Signatur und den Rückgabewert und beim Erzeugen des Delegate-Objektes gibt man den Methodennamen an. Hier ein Beispiel:

private delegate int SumDelegate(int a, int b);

private SumDelegate _sumOfInts;

public void ExampleSumUp()
{
_sumOfInts = new SumDelegate(this.sumInts);

Console.WriteLine("Summe von 1 und 2 ist: " + _sumOfInts(1, 2));
}

private int sumInts(int x, int y)
{
return x + y;
}

Zuerst wird ein Delegate namens 'SumDelegate' definiert. Danach wird ein Objekt definiert, welches den Typ des gerade angelegten Delegates besitzt. In der Example-Methode wird eine Instanz für den 'SumDelegate' erzeugt, wobei diese auf die Methode 'sumInts' zeigt. Danach wird der Delegate wie eine normale Methode aufgerufen und liefert ein Ergebnis zurück.

Was ist jetzt das Besondere an einem Delegate? Im obigen Beispiel könnte man die Methode 'sumInts' auch direkt aufrufen.

Zum einen legt man über die Delegate-Definition fest, welche Methoden-Parameter in der Methode vorhanden sein müssen und das wichtigste Argument ist, dass man Delegates synchron wie auch asynchron aufrufen kann.

Im obigen Beispiel wird der Delegate synchron aufgerufen. Ein asynchroner Aufruf eines Delegates sieht so aus:

Console.WriteLine("Summe von 2 und 3 ist: ");

IAsyncResult iaResult = _sumOfInts.BeginInvoke(2, 3, null, null);
// do more work
Console.WriteLine("jetzt wird gerechnet");
// output result
int theSum = _sumOfInts.EndInvoke(iaResult);
Console.WriteLine(theSum);

Den asynchronen Aufruf benutzt man dann, wenn man während der Ausführung einer lange dauernden Methode weiterarbeiten kann und erst später auf das Ergebnis angewiesen ist.

Auf die Problematik mit Delegates und dem Ändern von GUI-Komponenten bei der Ausführung von mehreren Threads gehe ich demnächst ein.

Friday, June 23, 2006

3D-Anwendungen mit Managed DirectX und C#  #

Für die Erstellung der Aibo-Programme haben wir uns auch mit der 3D-Programmierung mit DirectX und .NET beschäftigt. Seit DirectX 9 gibt es auch eine verwaltete Erweiterung namens Managed DirectX, mit der DirectX auch in .NET-Anwendungen einfach und effizient genutzt werden kann. In einem Tutorial zeigen wir Ihnen, wie man mit Hilfe von Managed DirectX eine einfache 3D-Anwendung in C# erstellen kann. Der Source-Code der Beispielanwendung ist ebenfalls verfügbar.

Wednesday, June 21, 2006

.NET-Software zur Steuerung des Sony AIBO  #

Der AIBO, die Roboter-Hunde von Sony, sind gerade während der Roboter-Weltmeisterschaft in Bremen (Robocup 2006) wieder ins Gespräch gekommen. Auch das ZfS Aachen hat sich mit den Aibos schon beschäftigt. Zur Präsentation auf Messen, Konferenzen, und Tagungen stehen den Zentren für Softwarekonzepte (ZfS) zwei Aibos zur Verfügung. Zur Steuerung dieser Aibos hat das ZfS Aachen zwei Programme mit dem .NET Framework von Microsoft entwickelt, die Sie bei uns im Download-Bereich finden können.

Die Aibos sind gerade übrigens bei unseren Kollegen in Karlsruhe im Einsatz, die momentan auf der Midvision 06 ausstellen.

Monday, June 19, 2006

Neues C#-HowTo-Dokument zum Download  #

Im Downloadbereich ist ab sofort ein neues HowTo-Dokument verfügbar: „Iteration von Objekteigenschaften mittels Reflection in C#“.

Inhalt dieses Dokuments ist der Einsatz der Reflection-Klasse PropertyInfo zur generischen Ermittlung und Verarbeitung von Objekteigenschaften.

Dieses Dokument ist nur registrierten Anwendern zugänglich. Eine Registrierung kann über das Registrierungs-Formular vorgenommen werden.

Start des .NET Framework und C# Blogs des ZfS Aachen!  #

Im .NET Framework und C# Blog werden wir in Zukunft Interessantes, Neues und Wissenswertes rund um das .NET Framework und die .NET-Sprache C# veröffentlichen und diskutieren.

 

Zusätzlich soll dieses Weblog zur Beantwortung typischer C#-FAQs beitragen.

Wer kennt es nicht, dass man manchmal relativ viel Zeit darauf verschwendet, Lösungen für immer wiederkehrende und eigentlich leicht lösbare Programmieraufgaben zu finden. Wir  möchten diese Plattform deshalb auch dazu nutzen, typische C#-Copy&Paste-Schnipsel im Laufe der Zeit zusammenzutragen und der C#-Community als schnelles Nachschlagewerk zur Verfügung zu stellen. Klassische FAQ-Beiträge werden z.B. die Konvertierung einfacher Datentypen oder die Formatierung von Fließkommazahlen darstellen.

 

Wir hoffen, damit dem einen oder anderen Entwickler dabei zu helfen, lästige Suchzeiten zu verkürzen und einen schnelleren Projektabschluss zu finden.

Archiv

© 2008 Fraunhofer FIT - Powered by: newtelligence dasBlog 1.8.5223.2 - Sign In

Feeds: RSS 2.0 | Atom 1.0