zurück zu den C#.NET
COM-Komponente schreiben
Ab und zu kann es hilfreich sein, eine in C# geschriebene Bibliothek in andere Programmiersprachen einzubinden.
Betrifft C#
Mit dem Component Object Model (COM) ist es auf Microsoft-Betriebssystemen möglich, eine Bibliothek für andere Programme bzw. Programmiersprachen ansprechbar und somit verwendbar zu machen.
Als Beispiel soll hier eine C# DLL (.NET 3.5, Visual Studio Express 2008, Windows Vista) dienen, die später mit Visual Basic Script (VBS) angesprochen wird. Hierzu erstellen wir zunächst ein neues Projekt des Typs Klassenbibliothek in Visual Studio. Als Name wähle ich hier COMTest.
Das Ziel soll es sein, eine Klasse der C#-Bibliothek in VBS zu instanzieren und Methoden des erstellten Objektes aufzurufen. Dazu gilt es zunächst, ein Interface für die Klasse zu erstellen, die später instanziert werden soll. Nur durch dieses Interface weiß VBS später, wie es möglich ist, unsere Klasse anzusprechen. Die Interface-Beschreibung werden wir später in eine Type Library (TLB) exportieren, auf die andere Programme zugreifen können. Durch diese TLB wissen sie, wie unsere Klasse angesprochen werden kann.
Erstellen Sie also eine neue Code-Datei für ein Interface, das beispielsweise so aussehen könnte:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace COMTest {
/// <summary>
/// Interface für eine Klasse, die aus COM heraus ansprechbar
/// sein soll.
/// </summary>
public interface IMyClass {
/// <summary>
/// Addiert zwei Zahlen. Das Ergebnis der Rechnung kann über
/// die Eigenschaft <see cref="Result"/> abgerufen werden.
/// </summary>
/// <param name="op1">Der erste Operand</param>
/// <param name="op2">Der zweite Operand</param>
void Add(int op1, int op2);
/// <summary>
/// Das Ergebnis der Addition. Wurde keine Addition durchgeführt, 0.
/// </summary>
int Result { get; }
/// <summary>
/// Zeigt eine kleine Informations-Box zur implementierenden Klasse an.
/// </summary>
void InfoBox();
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace COMTest {
/// <summary>
/// Interface für eine Klasse, die aus COM heraus ansprechbar
/// sein soll.
/// </summary>
public interface IMyClass {
/// <summary>
/// Addiert zwei Zahlen. Das Ergebnis der Rechnung kann über
/// die Eigenschaft <see cref="Result"/> abgerufen werden.
/// </summary>
/// <param name="op1">Der erste Operand</param>
/// <param name="op2">Der zweite Operand</param>
void Add(int op1, int op2);
/// <summary>
/// Das Ergebnis der Addition. Wurde keine Addition durchgeführt, 0.
/// </summary>
int Result { get; }
/// <summary>
/// Zeigt eine kleine Informations-Box zur implementierenden Klasse an.
/// </summary>
void InfoBox();
}
}
Sie sehen, dass mit COM auch Properties unterstützt werden, und gleichzeitig, dass weder Konstruktoren noch statische Klassen möglich sind. Beachten Sie, dass nur Programmiersprachen-Features verwendet werden sollten, die auch in den Zielsprachen verfügbar sind. Kann die Programmiersprache, die die COM-Klasse verwenden soll, nicht mit der Klasse umgehen, weil diese Sprachelemente enthält, die die Sprache nicht unterstützt, kann sie möglicherweise nicht richtig angesprochen werden.
Weiterhin sollten Sie nur Basisdatentypen verwenden, die in den meisten Sprachen vorhanden sind. Mit unsigned long werden Sie beispielsweise in VB Ihre Probleme haben.
Erstellen Sie nun die Klasse, die die Logik enthält, indem Sie das oben erstellte Interface implementieren:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace COMTest {
public class MyClass : IMyClass {
private int _Result = 0;
public void Add(int op1, int op2) {
checked {
_Result = op1 + op2;
}
}
public int Result {
get { return _Result; }
}
public void InfoBox() {
MessageBox.Show("MyClass v1.00");
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace COMTest {
public class MyClass : IMyClass {
private int _Result = 0;
public void Add(int op1, int op2) {
checked {
_Result = op1 + op2;
}
}
public int Result {
get { return _Result; }
}
public void InfoBox() {
MessageBox.Show("MyClass v1.00");
}
}
}
Damit unsere Bibliothek in VBS angesprochen werden kann, muss sie nun als COM-Visible deklariert werden. Dies geht im Menü über Projekt > COMTest-Eigenschaften... > Erstellen. Hier setzten Sie unten den Haken bei Für COM-Interop registrieren. Nun wechseln Sie links ins Register Signierung und weisen Visual Studio an, die Assembly (zu) signieren. Über (Neu...) im Dropdown-Menü können Sie ein neues Schlüsselpaar erstellen, mit dem die Assembly signiert wird. Dies sorgt dafür, dass keine Versionskonflikte bei mehreren Bibliotheken mit gleichem Namen auftreten, und dass Ihre DLL nicht durch eine unbefugte Person durch eine andere ausgetauscht werden kann. Sie können die generierte Schlüsseldatei für mehrere Projekte verwenden.
Nun müssen sowohl unser Interface als auch unsere Klasse als ComVisible deklariert werden. Hierzu fügen Sie in beiden Code-Dateien den Verweis auf den System.Runtime.InteropServices-Namespace hinzu. Setzen Sie dann vor die Deklaration des Interface diesen Code:
using System.Runtime.InteropServices;
// ...
[Guid("cf802340-c24b-11dd-ad8b-0800200c9a66")]
[ComVisible(true)]
public interface IMyClass {
// ...
// ...
[Guid("cf802340-c24b-11dd-ad8b-0800200c9a66")]
[ComVisible(true)]
public interface IMyClass {
// ...
Und für die Klasse MyClass:
using System.Runtime.InteropServices;
// ...
[Guid("dbf38bd0-c24b-11dd-ad8b-0800200c9a66")]
[ComVisible(true)]
public class MyClass : IMyClass {
private // ...
// ...
[Guid("dbf38bd0-c24b-11dd-ad8b-0800200c9a66")]
[ComVisible(true)]
public class MyClass : IMyClass {
private // ...
Die GUID ist ein eindeutiger Bezeichner, der auf dem System einzigartig sein muss. Ist er es nicht, kommt es zu einem Registry-Konflikt. Eine GUID kann z.B. hier generiert werden.
Nachdem Sie das Projekt kompiliert haben, können wir die Bibliothek dem System bekannt machen. Für gewöhnliche DLLs geht dies über das Windows-Tool regsvr32.exe. Da unsere DLL aber das .NET Framework benötigt, um überhaupt erst ausgeführt werfen zu können, müssen wir die DLL mit dem Tool regasm.exe registrieren, das bei jeder .NET Framework Installation mitgeliefert wird. Dieses Tool erzeugt einen Registrierungseintrag, der die .NET CLR startet, wenn unsere DLL angefordert wird.
Um die Sache etwas übersichtlicher zu gestalten, habe ich die DLL auf C:\ abgelegt.

Über /tlb wird eine Type Library (TLB) erstellt, die Auskunft darüber gibt, wie unsere Klasse anzusprechen ist (wenn man die Datei anschaut, wird man sich stark an das Interface erinnert fühlen). Mit /codebase wird die DLL in die Windows-Registrierung eingetragen, was dafür sorgt, dass man sie systemweit instanzieren kann, ohne wissen zu müssen, wo genau sie liegt.
Nun können wir eine VBS-Datei erstellen, die unsere Klasse anspricht. Dazu können wir die VBS-Funktion CreateObject verwenden, die eine COM-Klasse instanzieren kann. Die Signatur der Funktion lautet:
variant CreateObject (ByVal Klassenpfad)
Der Klassenpfad setzt sich aus dem Namen des Namespace und dem Namen der Klasse zusammen (in unserem Beispiel COMTest.MyClass). Hier sehen wir nun auch, dass ein Konstruktor in VBS überhaupt nicht angesprochen werden könnte. Um unsere Klasse nun zu testen, erstellen Sie eine neue VBS-Datei und fügen diesen Code ein:
set myObj = CreateObject("COMTest.MyClass")
myObj.Add 1, 2
MsgBox myObj.Result
myObj.InfoBox
myObj.Add 1, 2
MsgBox myObj.Result
myObj.InfoBox
Sie können das Skript nun mit dem Windows Scripting Host ausführen. Es sollte Ihnen zuerst 3 (Ergebnis der Addition) und dann die Box mit dem Namen und der Version unserer Klasse angezeigt werden. Erscheint stattdessen eine Fehlermeldung, sollten Sie die folgenden Punkte prüfen:
- Ein Interface für die anzusprechende Klasse muss existieren
- Die Klasse darf keine Konstruktoren enthalten
- Die Klasse sollte keine überladenen Methoden enthalten
- Etwaige Objekte als Rückgabewert von Methoden müssen selbst COM-Objekte sein
- Es sollten nur Basisdatentypen verwendet werden, die auch in der Zielsprache vorhanden sind
- Das Projekt ist signiert und als COM-Visible deklariert
- Die DLL ist mit RegAsm und /tlb /codebase erfolgreich registriert worden
- Sowohl Klasse als auch Interface sind public
- Sowohl Klasse als auch Interface verfügen über eine (unterschiedliche) GUID
- CreateObject wird der korrekte Pfad übergeben (Namespace.Klasse)
Abschließend bleibt zu sagen, dass COM ein sehr mächtiges Werkzeug ist. Sie können mit COM die komplette Palette der .NET Plattform auch in anderen Sprachen (wie VBS) verwenden, wenn auf dem Zielsystem das .NET Framework installiert ist. Sie können COM-Komponenten im Browser (VBS), auf Servern (mit PHP), unter Windows (mit VBS), in Office-Anwendungen (mit VBA) und in fast jeder Programmiersprache einsetzen.
Artikel bewertenIch würde mich freuen wenn Sie sich schnell Zeit nehmen würden, um diesen Artikel zu bewerten. |
BewertungenDieser Artikel wurde von 16 Benutzern mit durchschnittlich 9.81 von 10 möglichen Punkten bewertet. Ähnliche ArtikelBibliothek (DLL) registrieren - 98 (SE) / ME / 2000 / XP Bibliothek (DLL) registrieren - Vista |
Allgemeine Informationen
Dieser Artikel wurde am 04.12.2008 erstellt und bisher 2100 mal aufgerufen. Wenn Sie Fragen zu diesem Artikel haben, wenden Sie sich bitte per E-Mail an info@computerleben.net. Supportanfragen werden ausschließlich im Forum beantwortet.
Weitere Optionen
Share
