Visual Basic Fusion: Best Practices für den gemeinsamen Einsatz von VB 6.0 und VB .NET

Veröffentlicht: 18. Jun 2007

Von Scott Swigart

Eine Microsoft Visual Basic 6.0-Anwendung kann auf .NET-Klassenbibliotheken zugreifen. Dazu muss sie allerdings eine Interoperabilitätsschicht verwenden, den Client Callable Wrapper. Dieser umhüllt die gewünschte .NET-Klasse und macht sie verfügbar wie ein traditionelles COM-Objekt , das von jeder Umgebung verwendet werden kann, die COM-Objekte nutzen kann. Hier erfahren Sie, wie diese Wrapper erstellt werden.

Codebeispiel für diesen Artikel herunterladen.

Auf dieser Seite

 Übersicht
 Erläuterungen zur Visual Basic 6.0- und Visual Basic .NET-Laufzeit
 Aufrufe in Framework
 Erstellen von Wrappern mit Visual Basic .NET
 Vergleich der Optionen
 Verwenden des Beispielcodes
 Zusammenfassung
 Der Autor

Übersicht

Viele Organisationen verfügen über eine umfangreiche Microsoft Visual Basic 6.0-Codebasis und möchten im Hinblick auf diesen Legacycode optimale Entscheidungen treffen. Es gibt grundsätzlich drei Möglichkeiten im Umgang mit Visual Basic 6.0-Anwendungen: Sie können eine Visual Basic 6.0-Anwendung so beibehalten wie sie ist, ohne eine neue Technologie in diese Legacyanwendung zu integrieren. Sie können die Visual Basic 6.0-Anwendung vollständig zu Visual Basic .NET migrieren. Oder Sie können Ihren Visual Basic 6.0-Code beibehalten und mit Visual Basic .NET arbeiten, um dadurch Ihrer vorhandenen Anwendung mühelos eine beliebige Funktionalität aus .NET Framework hinzuzufügen. Die Best Practices für diese letzte Option, die auch als Visual Basic Fusion bezeichnet wird, werden im vorliegenden Artikel behandelt.

 

Erläuterungen zur Visual Basic 6.0- und Visual Basic .NET-Laufzeit

Visual Basic 6.0-Anwendungen sind im Grunde COM-Anwendungen. Wenn Sie bestimmte Vorgänge in Visual Basic 6.0 durchführen wollen, wie z. B. das Zugreifen auf eine Datenbank oder Erstellen einer Benutzeroberfläche, fügen Sie Ihrem Projekt die entsprechende COM-Komponente als Control oder per Verweis als Bibliothek hinzu und verwenden dann die darin enthaltene Funktionalität. Auch andere Anwendungen machen in der Regel die Funktionalität durch COM-Komponenten verfügbar. Zum Beispiel kann eine Visual Basic 6.0-Anwendung Microsoft Word oder Excel automatisieren, weil diese Anwendungen ihre Funktionalität über COM-Schnittstellen verfügbar machen.

Visual Basic .NET-Anwendungen sind nicht COM-basiert und machen standardmäßig keine COM-Schittstellen verfügbar. Sie greifen auf die Funktionalität in den .NET-Klassenbibliotheken zu. Microsoft .NET Framework umfasst Tausende von Klassenbibliotheken, anhand derer Visual Basic .NET-Anwendungen mit Datenbanken kommunizieren und auf das Internet, die Registrierung, das Dateisystem, das Ereignisprotokoll sowie die Systeminformationen zugreifen können und mehr. Das Ausmaß der Funktionalität, die in den .NET Framework-Klassenbibliotheken (Framework Class Libraries, FCL) verfügbar ist, ist bedeutend größer als die in Visual Basic 6.0 verfügbare Funktionalität.

Visual Basic 6.0 und Visual Basic .NET sind auf zueinander nicht kompatiblen Technologien aufgebaut. Eine Visual Basic 6.0-Anwendung kann dennoch auf .NET-Klassenbibliotheken zugreifen. Dazu muss sie aber über eine Interoperabilitätsschicht gehen, den Client Callable Wrapper. Dieser umhüllt die gewünschte .NET-Klasse und macht sie verfügbar, sodass sie wie ein traditionelles COM-Objekt erscheint. So kann es jeder Umgebung verwendet werden, die COM-Objekte nutzen kann (Visual Basic 6.0, Visual Basic 5.0, ASP, VBA, VBScript und so weiter).

 

Aufrufe in Framework

Wie im Artikel „Aufrufen von .NET Framework-Funktionen aus vorhandenen Visual Basic 6.0-Anwendungen“ beschrieben, besteht der erste Schritt für Aufrufe in das .NET Framework im Registrieren der erforderlichen .NET Framework-DLL (auch Assembly genannt) als COM-Objekt. Dies kann mit dem regasm-Dienstprogramm erreicht werden, das im .NET Framework-SDK enthalten ist. Letzteres wird auch als Teil des Produkts Visual Basic Express mit installiert. Wenn Sie nicht über Visual Studio 2005 verfügen, empfiehlt es sich dringend, dass Sie das kostenlos erhältliche Visual Basic Express herunterladen und installieren.

Beispiel 1: Registrieren der .NET-Bibliothek System.dll für das Verwenden von Visual Basic 6.0 aus

  1. Klicken Sie auf Start | Ausführen.

  2. Geben Sie im Dialogfeld Ausführen CMD ein, und klicken Sie auf OK.

  3. Geben Sie cd C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 ein.

  4. Geben Sie regasm system.dll ein.

Sobald die Assembly registriert wurde, können Sie von Visual Basic 6.0 aus einen Verweis hinzufügen, als ob es sich um ein COM-Objekt handeln würde:

Abbildung 1: Hinzufügen eines Verweises zu system.dll von Visual Basic 6.0 aus
Abbildung 1: Hinzufügen eines Verweises zu system.dll von Visual Basic 6.0 aus

Visual Basic 6.0 kann die System.dll-.NET-Assembly aufrufen, weil ein von COM aufrufbarer Wrapper dafür erstellt wurde. Damit eine .NET-Klasse und ihre Funktionen in einem von COM aufrufbarem Wrapper erscheinen, muss die .NET-Klasse jedoch eine Reihe von relativ einschränkenden Regeln befolgen. Demzufolge wird nur ein sehr kleiner Prozentsatz der Klassen in System.dll direkt von Visual Basic 6.0 aufrufbar sein. Eine Funktion, die von Visual Basic 6.0 aufrufbar ist, ist die Funktion WebClient.DownloadFile.

Dim webDownload As System.WebClient
webDownload = New System.WebClient
webDownload.downloadFile( _
    "http://www.ssec.wisc.edu/data/west/latest_westir.jpg", _
    App.Path & "\latest_westir.jpg")

Codebeispiel 1: Aufrufen der DownloadFile-Funktion von Visual Basic 6.0 aus

 

Erstellen von Wrappern mit Visual Basic .NET

Das oben genannte Beispiel soll nicht den falschen Eindruck erwecken, dass Sie Regasm einfach auf eine beliebige .NET-Assembly anwenden können und auf diese Weise die gesamte .NET-Funktionalität erhalten, die dann in Visual Basic 6.0 verfügbar ist. Wenn Sie .NET Framework, .NET-Komponenten von Drittanbietern oder Open Source-.NET-Bibliotheken aufrufen wollen, müssen Sie in den meisten Fällen Wrapperklassen in Visual Basic .NET schreiben. Das liegt daran, dass eine .NET-Klasse relativ strengen Regeln folgen muss, um sich ordnungsgemäß als ein COM-Objekt zu präsentieren, und die meisten .NET-Klassen befolgen diese Regeln nicht.

Um auf die .NET-Funktionalität zuzugreifen, erstellen Sie eine Klasse in Visual Basic .NET, die die Regeln für die COM-Interoperabilität befolgt, und diese Klasse ruft den gewünschten .NET-Code für die Visual Basic 6.0-Anwendung auf.

Abbildung 2: Aufrufen von .NET Framework in Visual Basic 6.0 über Visual Basic .NET-Wrapperklassen
Abbildung 2: Aufrufen von .NET Framework in Visual Basic 6.0 über Visual Basic .NET-Wrapperklassen

Einfache Wrapperklasse

Ein einfaches Beispiel stellt die .NET Framework-GUID-Klasse dar. Eine GUID (Globally Unique Identifier) ist ein „eindeutiger Bezeichner“. GUIDs werden an vielen Stellen in Windows verwendet, um COM-Objekte, Dateien, Benutzer usw. (im Grunde fast alles) eindeutig zu identifizieren. Sie treten sichtbar in Form von Zeichenfolgen auf, wie z. B.: 13427d57-ccb5-42fd-91f7-b49d4c2ae9a3. Eine GUID zeichnet sich insbesondere durch Folgendes aus: Wenn Sie eine GUID ordnungsgemäß generieren, können Sie sich absolut sicher sein, dass sonst niemand genau dieselbe GUID generieren wird.

In Visual Basic 6.0 gibt es keine einfache Möglichkeit, eine GUID zu generieren. In Visual Basic .NET ist dazu dagegen nur eine Codezeile erforderlich:

Dim g as Guid = Guid.NewGuid()

Codebeispiel 2: Generieren einer GUID in Visual Basic .NET

Leider wurde die GUID-Klasse nicht so erstellt, dass Sie sie direkt von Visual Basic 6.0 aufrufen können. Um diese Funktionalität von Visual Basic 6.0 aus zu verwenden, erstellen Sie eine sehr einfache Visual Basic .NET-Wrapperklasse. Diese Visual Basic .NET Wrapperklasse wird als COM-Objekt verfügbar gemacht, das von Visual Basic 6.0 aus einsetzbar ist. Sie wird den erforderlichen Aufruf der .NET Framework GUID-Klasse vornehmen.

Einzelheiten zum Erstellen von Wrapperklassen finden Sie englischsprachig unter „Can I Interest You in 5000 Classes?” besprochen, die Grundlagen werden hier in deutscher Sprache wiederholt:

Beispiel 2: Erstellen des Visual Basic .NET-Wrappers für die GUID Klasse

  1. Laden Sie den Beispielcode für diesen Artikel herunter, und extrahieren Sie ihn.

  2. Kopieren Sie die ComClass.zip-Datei in den Ordner C:\Dokumente und Einstellungen\[Benutzername]\Eigene Dateien\Visual Studio 2005\Templates\ItemTemplates\Visual Basic.

    Wenn Sie Visual Studio 2005 verwenden, können Sie Schritt 2 auslassen. Visual Basic Express hingegen umfasst standardmäßig keine COM-Klassenvorlage. Diese Vorlage ist jedoch sehr nützlich, um .NET Framework als COM-Objekte verfügbar zu machen. Durch Kopieren der ComClass.zip-Datei in diesen Ordner wird die COM-Klassenvorlage für Visual Basic Express verfügbar gemacht.

  3. Wählen Sie in Visual Basic 2005 / Express den Menübefehl Datei | Neues Projekt aus.

  4. Im Dialogfeld Neues Projekt:

    1. Wählen Sie die Vorlage Klassenbibliothek aus.

    2. Geben Sie unter Name als Namen NetFxWrapper ein. Dieser Name wird als Name der Komponente verwendet und in der Liste der Verweise angezeigt, die in Visual Basic 6.0 verfügbar sind.

    Abbildung 3: Erstellen des Wrapperprojekts in Visual Basic .NET
    Abbildung 3: Erstellen des Wrapperprojekts in Visual Basic .NET

  5. Klicken Sie auf OK.

  6. Löschen Sie im Projektmappen-Explorer die Option Class1.

  7. Wählen Sie den Befehl Projekt | Neues Element hinzufügen aus.

  8. Im Dialogfeld Neues Element hinzufügen:

    1. Wählen Sie für Vorlagen die Option COM-Klasse aus.

    2. Geben Sie im Feld Name GuidWrapper ein.

      Abbildung 4: Erstellen der Visual Basic .NET-Wrapper-COM-Klasse
      Abbildung 4: Erstellen der Visual Basic .NET-Wrapper-COM-Klasse

  9. Klicken Sie auf Hinzufügen.

  10. Geben Sie in Zeile 20 (nach End Sub und vor End Class) Folgendes ein:

    Public Function NewGuid() As String Dim g As Guid = Guid.NewGuid() Return g.ToString() End Function
    

    Codebeispiel 3: Wrapperfunktion in Visual Basic .NET

    Dadurch wird eine Instanz der GUID-Klasse erstellt, die einem neu generierten GUID-Wert zugewiesen wird. Daraufhin wird der GUID-Wert in eine Zeichenfolge konvertiert, die zurückgegeben wird.

  11. Wählen Sie den Menübefehl Erstellen | NetFxWrapper erstellen aus. Dadurch wird die Komponente kompiliert und als COM-Objekt registriert.

Nachdem Sie nun den Wrapper erstellt haben, können Sie ihn von Visual Basic 6.0 aus aufrufen.

Beispiel 3: Verwenden des Wrappers von Visual Basic 6.0 aus

  1. Starten Sie Visual Basic 6.0.

  2. Wählen Sie im Dialogfeld Neues Projekt die Option Standard Exe aus, und klicken Sie auf Öffnen.

  3. Wählen Sie den Menübefehl Projekt | Verweise aus.

  4. Fügen Sie einen Verweis auf NetFxWrapper hinzu.

    Abbildung 5: Hinzufügen eines Verweises zu einem in Visual Basic .NET erstellten COM-Objekt
    Abbildung 5: Hinzufügen eines Verweises zu einem in Visual Basic .NET erstellten COM-Objekt

  5. Fügen Sie dem Formular eine Befehlsschaltfläche (CommandButton) und ein Textfeld (TextBox) hinzu.

  6. Belegen Sie die Eigenschaft Caption des CommandButtons mit dem Wert Generate.

  7. Geben Sie für das Klickereignis des CommandButtons Folgendes ein:

    Private Sub Command1_Click()
    Dim gw As NetFxWrapper.GuidWrapper
    Set gw = New NetFxWrapper.GuidWrapper
    Text1.Text = gw.NewGuid
    End Sub
    

    Codebeispiel 4: Aufrufen des Wrappers von Visual Basic 6.0

  8. Führen Sie die Anwendung aus. Jedes Mal, wenn Sie auf die Schaltfläche klicken, ruft die Visual Basic 6.0-Anwendung den Visual Basic .NET-Wrapper auf und generiert eine neue GUID. Die GUID wird im Textfeld angezeigt.

    Abbildung 6: Anzeigen der GUID
    Abbildung 6: Anzeigen der GUID

Regeln für das Erstellen von Wrappern

Die Wrapperklasse ist notwendig, weil die GUID-Klasse sich nicht an die Regeln für die COM-Interoperabilität hält. Ihre Wrapperklasse muss folgende Regeln einhalten:

  1. Der Wrapper muss einen Standardkonstruktor bereitstellen

    In Visual Basic 6.0 erstellen Sie zuerst eine Instanz eines Objekts. Anschließend verwenden Sie Eigenschaften und Methoden, um das Objekt zu initialisieren. Beispiel:

    Dim cn As ADODB.Connection
    Set cn = New ADODB.Connection
    cn.ConnectionString = _
        "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=mydb.mdb;" & _
        "User Id=admin;Password=;"
    

    Codebeispiel 5: Initialisieren eines Verbindungsobjekts in Visual Basic 6.0

    Um ein Verbindungsobjekt einzurichten, müssen Sie zuerst eine Instanz davon erstellen und dann deren Eigenschaften, wie z. B. ConnectionString, festlegen. In Visual Basic 6.0 müssen das Erstellen eines Objekts und das Initialisieren seiner Eigenschaften in separaten Schritten erfolgen.

    In Visual Basic .NET hingegen können Sie oft die wichtigsten Initialisierungsinformationen gleich beim Erstellen der Objektinstanz mit angeben. Der entsprechende Code in Visual Basic .NET lautet für das vorangehende Besipiel:

    Dim cn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" & _
    "Data Source=mydb.mdb;User Id=admin;Password=;")
    

    Codebeispiel 6: Übergabe von Argumenten an den Konstruktor in Visual Basic .NET

    Wie Sie sehen, wird das Objekt in einer einzigen Codezeile erstellt und initialisiert. Dies ist möglich, weil .NET-Typen über eine Methode „Sub New“ verfügen, die aufgerufen wird, wenn das Objekt erstellt worden ist, und diese Sub New-Methode kann Argumente annehmen. Eine Klasse kann sogar über mehrere Sub New-Konstruktormethoden verfügen, die jeweils unterschiedliche Typen bzw. eine unterschiedliche Anzahl von Argumenten annehmen.

    Public Sub New()
    End Sub
    
    Public Sub New(ByVal connectionString As String)
    End Sub
    

    Codebeispiel 7: Visual Basic .NET-Klassenkonstruktoren

    Wenn Sie eine Instanz einer Klasse erstellen, ermittelt der Visual Basic .NET-Compiler anhand von Anzahl und Typ der mit übergebenen Argumente, welche vorhandene Sub New-Methode automatisch aufgerufen werden soll. Wenn Sie eine Instanz von OleDbConnection ohne jegliche Argumente erstellt haben, würde sie die Sub New-Methode aufrufen, die keine Argumente annimmt. Wenn Sie eine Instanz von OleDbConnection mit einem Verbindungszeichenfolgenargument erstellen, generiert der Compiler automatisch einen Aufruf an die Sub New-Methode, die eine Zeichenfolge als ein Argument annimmt.

    Die Sub New-Methode, die keine Argumente annimmt, ist als „Standardkonstruktor“ bekannt, d. h. dass sie standardmäßig aufgerufen wird, wenn keine Argumente bereitgestellt werden.

    Da Visual Basic 6.0 keine Argumente weiterleiten kann, wenn Sie eine Instanz eines Objekts gerade erst erstellen, muss eine .NET-Klasse einen Standardkonstruktor bereitstellen, andernfalls können Sie ihn nicht direkt von Visual Basic 6.0 aus verwenden. Viele der .NET Framework-Klassen sind nicht direkt einsetzbar, weil sämtliche ihrer Sub New-Methoden Argumente anfordern. Sie stellen also keinen Standardkonstruktor bereit. Deshalb haben Sie keine Möglichkeit, eine Instanz davon aus Visual Basic 6.0 heraus zu erstellen.

    Sie können für diese Objekte Wrapperklassen erstellen. Ihr Wrapper macht einen Standardkonstruktor verfügbar. Wenn Ihr Wrapper jedoch eine Instanz der eigentlichen .NET Framework-Klasse erstellt, übergibt er die nötigen Argumente an eine entsprechende Sub New-Methode dieser Klasse.

    Ein einfaches Beispiel stellt die .NET Framework-Klasse FileInfo dar. Mit dieser Klasse erhalten Sie viele Merkmale einer Datenträgerdatei. Sie verfügt jedoch nicht über einen Standardkonstruktor. Die Sub New-Methode für FileInfo erfordert den Pfad zur gewünschten Datei, sie kann jedoch folgendermaßen gewrappt werden:

    Private fi As FileInfo
    
    Public Sub New()
    End Sub
    
    Public Sub Initialize(ByVal filePath As String)
    fi = New FileInfo(filePath)
    End Sub
    

    Codebeispiel 8: Visual Basic .NET-Wrapper für FileInfo

    Dieser Wrapper enthält eine Sub New-Methode, die keine Argumente annimmt. Dadurch kann diese Klasse für COM Intertop registriert werden, sodass eine Visual Basic 6.0-Anwendung eine Instanz davon erstellen kann. Das interne FileInfo-Objekt wird so lange nicht erstellt, bis die Visual Basic 6.0-Anwendung die Initialize-Methode aufruft. Dies würde von Visual Basic 6.0 folgendermaßen verwendet werden:

    Dim fi As NetFxWrapper.FileInfoWrapper
    Set fi = New NetFxWrapper.FileInfoWrapper
    fi.Initialize ("c:\somefile.txt")
    

    Codebeispiel 9: Verwenden des FileInfo-Wrappers von Visual Basic 6.0 aus

  2. Viele Datentypen müssen von Visual Basic 6.0 in Visual Basic .NET konvertiert werden

    Die meiste Arbeit beim Erstellen eines Wrappers macht das Konvertieren von Visual Basic .NET-Datentypen aus, und zwar in Elemente, mit denen Visual Basic 6.0 arbeiten kann. Betrachten Sie die folgenden beiden Methoden. Die eine gibt eine Zeichenfolge und die andere einen GUID-Datentyp zurück:

    Public Function NewGuidAsString() As String Dim g As Guid = Guid.NewGuid() _
    Return g.ToString() End Function Public Function NewGuidAsGuid () As Guid _
    Dim g As Guid = Guid.NewGuid() Return g End Function
    

    Codebeispiel 10: Wrapperfunktion in Visual Basic .NET

    Das Aufrufen von NewGuidAsString von Visual Basic 6.0 aus funktioniert gut, da Zeichenfolgen zwischen Visual Basic 6.0 und Visual Basic. NET mühelos ausgetauscht werden. Das Aufrufen von NewGuidAsGuid von Visual Basic 6.0 aus generiert jedoch den folgenden Fehler:

    Abbildung 7: Fehlermeldung nach dem Aufruf von NewGuidAsGuid von Visual Basic 6.0 aus
    Abbildung 7: Fehlermeldung nach dem Aufruf von NewGuidAsGuid von Visual Basic 6.0 aus

    Der Grund dafür ist, dass ein Objekt vom Typ GUID nicht direkt von Visual Basic .NET an Visual Basic 6.0 übermittelt werden kann. Wenn Sie Wrapper für .NET-Klassen erstellen, werden Sie die meiste Zeit mit dem Konvertieren von .NET-Datentypen in von Visual Basic 6.0 verwendbare Typen beschäftigt sein.

    Sie können außerdem das .NET-Attribut MarshalAs verwenden, um anzugeben, welcher Visual Basic 6.0-Typ für Argumente und Rückgabewerte verwendet werden soll. Wenn zum Beispiel eine Visual Basic .NET-Funktion einen Dezimaldatentyp zurückgibt, kann diese Funktion von Visual Basic 6.0 nicht aufgerufen werden. Sie können jedoch angeben, dass der Rückgabewert in einen Währungstyp umgewandelt werden soll. Dadurch kann Visual Basic 6.0 die Funktion fehlerlos ausführen.

    Public Function ReturnDecimal() As _
    <Runtime.InteropServices.MarshalAs(Runtime.InteropServices.UnmanagedType.Currency)> _
    Decimal Return 1.1 End Function
    

    Codebeispiel 11: Verwenden von MarshalAs für das Konvertieren von VB 6.0- und VB .NET-Typen

    In der folgenden Tabelle werden die automatischen Konvertierungen aufgelistet, die zwischen Visual Basic .NET- und Visual Basic 6.0-Typen erfolgen.

    Tabelle 1: Typkonvertierung von Visual Basic .NET in Visual Basic 6.0 Visual Basic .NET-Typ Visual Basic 6.0-Typ Boolean Boolean Byte Byte Char Nicht unterstützt, geben Sie Visual Basic 6.0 stattdessen eine Zeichenfolge zurück. DateTime Date Decimal Nicht unterstützt, geben Sie den Wert stattdessen als „Single“ bzw. „Double“ zurück, oder verwenden Sie das MarshalAs-Attribut, um ihn als Visual Basic 6.0-Währung zurückzugeben. Double Double Guid Nicht unterstützt, geben Sie Visual Basic 6.0 stattdessen eine Zeichenfolge zurück. Integer Long Long Nicht unterstützt Object Object SByte Nicht unterstützt in Visual Basic 6.0, geben Sie den Wert stattdessen als „Integer“ zurück. Short Integer Single Single String String TimeSpan Nicht unterstützt, verwenden Sie stattdessen Funktionen wie TotalSeconds oder TotalMinutes, und geben Sie den Wert als „Double“ zurück.

  3. Freigegebene Funktionen arbeiten nicht zusammen

    In Visual Basic 6.0 verfügen Sie über globale Funktionen, die von einem beliebigen Codeabschnitt aufgerufen werden können. Bei globalen Funktionen ist es schwer zu erkennen, dass zwei verschiedene globale Funktionen logisch verwandt sind. In Visual Basic .NET können Sie stattdessen globale Funktionen innerhalb einer Klasse gruppieren. Der Vorteil ist, dass Sie die Funktion mithilfe des Namens der Klasse aufrufen können, ohne eine Instanz der Klasse erstellen zu müssen:

    If Not File.Exists(someFile) Then MessageBox.Show("File not found") End If
    

    Codebeispiel 12: Freigegebene Funktion

    In diesem Beispiel wird die Funktion Exists direkt aus der Klasse File aufgerufen. Der Code hat keine Instanz der Klasse File erstellt, um diese Methode aufzurufen. Stattdessen wird Exists direkt vom Typ File aus aufgerufen. Diese Funktionen werden als freigegebene oder statische Funktionen bezeichnet und im gesamten .NET Framework verwendet.

    Ein Problem von freigegebenen Funktionen besteht darin, dass sie nicht mit Visual Basic 6.0 zusammenarbeiten. Damit Visual Basic 6.0 eine Funktion aufruft, muss die Funktion tatsächlich global sein, oder sie muss von einer Instanz einer Klasse aufgerufen werden. Freigegebene Funktionen erfüllen diese Bedingungen nicht.

    Die Lösung ist das Erstellen eines Wrappers, sodass Sie eine Instanz des Wrappers erstellen und dann mit dem Wrapper die freigegebene Funktion aufrufen können.

    Imports System.IO <ComClass(FileWrapper.ClassId, FileWrapper.InterfaceId, FileWrapper.EventsId)> _
    Public Class FileWrapper Public Const ClassId As String = "1596574F-9EE1-4439-854B-DF503099CEAE" _
    Public Const InterfaceId As String = "02F98DBC-9298-4E9D-A991-E618C1B1BC53" _
    Public Const EventsId As String = "2286FD23-B22D-4D49-B2CE-F3CFEC5C1CA5" Public Sub New() MyBase.New() _
    End Sub Public Function Exists(ByVal fileName As String) As Boolean Return File.Exists(fileName) _
    End Function End Class
    

    Codebeispiel 13: Wrapper, der eine freigegebene Funktion aufruft

    Die FileWrapper-Klasse kann von Visual Basic 6.0 aus erstellt werden, weil sie einen Standardkonstruktor verfügbar macht. Wenn die Funktion Exists aufgerufen wird, ruft sie die freigegebene File.Exists-.NET-Funktion auf und gibt die Ergebnisse zurück. Visual Basic 6.0 ruft eine Instanzmethode von FileWrapper auf, und FileWrapper ruft eine freigegebene Methode der .NET Framework File-Klasse auf.

    Von Visual Basic 6.0 aus kann dies folgendermaßen verwendet werden:

    Private Sub Command5_Click() Dim fw As New NetFxWrapper.FileWrapper Label2 = fw.Exists("c:\platform.ini") End Sub
    

    Codebeispiel 14: Verwenden von File.Exists von Visual Basic 6.0 aus

  4. Wrapper sollten keine überladenen Funktionen verwenden

    .NET Framework ermöglicht das Vorhandensein mehrerer Funktionen mit genau demselben Namen, jedoch unterschiedlichen Argumenten. Beachten Sie die folgenden Aspekte:

    Public Sub Save(ByVal fileName As String) _image.Save(fileName) End Sub Public Sub Save(ByVal fileName _
    As String, ByVal format As ImageFormatWrapper) Dim imageFormat As Imaging.ImageFormat Select Case _
    format Case ImageFormatWrapper.Bmp imageFormat = Imaging.ImageFormat.Bmp Case _
    ImageFormatWrapper.Emf imageFormat = Imaging.ImageFormat.Emf Case _
    ImageFormatWrapper.Exif imageFormat = Imaging.ImageFormat.Exif Case _
    ImageFormatWrapper.Gif imageFormat = Imaging.ImageFormat.Gif Case _
    ImageFormatWrapper.Icon imageFormat = Imaging.ImageFormat.Icon Case _
    ImageFormatWrapper.MemoryBmp imageFormat = Imaging.ImageFormat.MemoryBmp Case _
    ImageFormatWrapper.Png imageFormat = Imaging.ImageFormat.Png Case _
    ImageFormatWrapper.Tiff imageFormat = Imaging.ImageFormat.Tiff Case _
    ImageFormatWrapper.Wmf imageFormat = Imaging.ImageFormat.Wmf End _
    Select _image.Save(fileName, imageFormat) End Sub
    

    Codebeispiel 15: Überlastete Funktionen in Visual Basic .NET

    Eine Funktion nimmt einen Dateinamen als ein Argument an, und die andere nimmt ein zusätzliches Bildformatargument an. Beide Funktionen werden Save genannt. Wenn diese Funktionen von Visual Basic .NET aus aufgerufen werden, kann der Compiler festlegen, welche Funktion aufgrund der übermittelten Argumente aufgerufen werden soll. Wenn nur ein Argument weitergeleitet wird, wird die erste Funktion aufgerufen. Wenn zwei Argumente weitergeleitet werden, wird die zweite Funktion aufgerufen.

    COM unterstützt überladene Funktionen nicht. Wenn diese Klasse also durch COM-Interoperabilität verfügbar gemacht wird, muss der COM-Wrapper eindeutige Funktionsnamen für diese Funktionen generieren. In Visual Basic 6.0 erscheinen sie folgendermaßen:

    Abbildung 8: Aufrufen überladener Funktionen von Visual Basic 6.0 aus
    Abbildung 8: Aufrufen überladener Funktionen von Visual Basic 6.0 aus

    Beachten Sie, dass die Save-Funktionen Save und Save_2 genannt wurden. Auf diese Weise können Sie identifizieren, welche Funktion Sie von Visual Basic 6.0 aus aufrufen wollen. Die Namen sind jedoch nicht beschreibend. Es empfiehlt sich, in Ihrem Wrapper keine Überladungen zu verwenden und stattdessen jeder Funktion einen eindeutigen Namen zu geben:

    Public Sub Save(ByVal fileName As String) _image.Save(fileName) End Sub Public Sub _
    SaveWithImageFormat(ByVal fileName As String, _ ByVal format As ImageFormatWrapper) _
    Dim imageFormat As Imaging.ImageFormat Select Case format Case _
    ImageFormatWrapper.Bmp imageFormat = Imaging.ImageFormat.Bmp Case _
    ImageFormatWrapper.Emf imageFormat = Imaging.ImageFormat.Emf Case _
    ImageFormatWrapper.Exif imageFormat = Imaging.ImageFormat.Exif Case _
    ImageFormatWrapper.Gif imageFormat = Imaging.ImageFormat.Gif Case _
    ImageFormatWrapper.Icon imageFormat = Imaging.ImageFormat.Icon Case _
    ImageFormatWrapper.MemoryBmp imageFormat = Imaging.ImageFormat.MemoryBmp Case _
    ImageFormatWrapper.Png imageFormat = Imaging.ImageFormat.Png Case _
    ImageFormatWrapper.Tiff imageFormat = Imaging.ImageFormat.Tiff Case _
    ImageFormatWrapper.Wmf imageFormat = Imaging.ImageFormat.Wmf End _
    Select _image.Save(fileName, imageFormat) End Sub
    

    Codebeispiel 16: Eindeutige Namen für Funktionen

    Jetzt hat jede Funktion einen eindeutigen Namen, und es ist leichter, sie von Visual Basic 6.0 aus zu verwenden.

    Abbildung 9: Funktionen mit eindeutigen Namen
    Abbildung 9: Funktionen mit eindeutigen Namen

  5. Wrapper sollten im globalen Assemblycache platziert werden

    Wenn ein COM-Objekt registriert ist, enthält die Systemregistrierung den Dateipfad zur COM-Objekt-DLL. Auf diese Weise kann das Betriebssystem diese DLL finden und sie in den Speicher laden, wenn Ihr Programm eine Instanz des COM-Objekts erstellt.

    .NET-Assemblys funktionieren anders: Das .NET Framework erwartet, dass sich die Assembly am gleichen Ort wie die EXE-Datei befindet, die sie verwendet, oder es erwartet, dass sich die Assembly an einem Ort namens „globaler Assemblycache“ (GAC) befindet. Um sicher zu sein, dass Ihre .NET-Wrapperklassen zur Laufzeit stets gefunden werden können, sollten sie im GAC platziert werden.

    Das Platzieren einer Assembly im GAC ist ein Vorgang, der aus zwei Schritten besteht. Zuerst muss die Assembly signiert werden. Dies kann folgendermaßen ausgeführt werden:

    1. Kehren Sie zum NetFxWrapper-Projekt in Visual Basic Express zurück.

    2. Doppelklicken Sie im Projektmappen-Explorer auf My Project. Daraufhin werden die Projekteigenschaftenseiten geöffnet.

    3. Klicken Sie auf die Registerkarte Signierung.

    4. Klicken Sie auf Kontrollkästchen Signieren der Assembly.

    5. Klicken Sie im Dropdownmenü auf die Option Schlüsseldatei mit starkem Namen auswählen und anschließend auf <Neu...>.

    6. Geben Sie unter Schlüsseldateiname MyKeyFile ein.

    7. Deaktivieren Sie das Kontrollkästchen Schlüsseldatei mit Kennwort schützen.

    8. Klicken Sie auf OK.

    9. Wählen Sie den Menübefehl Erstellen | NetFxWrapper erstellen aus.

      Dadurch wird dem Projekt eine Schlüsseldatei hinzugefügt, und jedes Mal, wenn das Projekt kompiliert wird, wird die entstehende DLL mit diesem Schlüssel signiert. Assemblys müssen signiert werden, bevor sie im globalen Assemblycache platziert werden können.

    10. Navigieren Sie zu Start | Ausführen.

    11. Geben Sie cmd ein, und klicken Sie auf OK, um ein Befehlsfenster zu öffnen.

    12. Navigieren Sie im Befehlsfenster zu dem Verzeichnis, in dem die Wrapperklasse kompiliert wurde. Auf meinem Computer ist dies folgendes Verzeichnis: C:\Dokumente und Einstellungen\Administrator\Eigene Dokumente\Visual Studio 2005\Projects\NetFxWrapper\NetFxWrapper\bin\Release.

    13. Geben Sie "C:\Programme\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil" -i NetFxWrapper.dll ein.

    Hinweis
    Beachten Sie vor allem die Anführungszeichen um den gacutil-Pfad. In der Regel erhalten Sie eine Meldung, dass die Assembly erfolgreich dem globalen Assemblycache hinzugefügt wurde.

    Wenn Sie eine Visual Basic 6.0-Anwendung bereitstellen, die eine Wrapperklasse verwendet, muss Ihr Anwendungsinstallationsprogramm gacutil verwenden, um die Wrapperklasse in den GAC zu installieren.

 

Vergleich der Optionen

In diesem Artikel liegt der Schwerpunkt auf den Best Practices für das Verwenden der Visual Basic Fusion-Methode. Es lohnt sich jedoch, alle Möglichkeiten zu untersuchen, die für Visual Basic 6.0-Anwendungen zur Verfügung stehen, und zu ermitteln, ob Visual Basic Fusion oder eine andere Taktik die beste Option für eine bestimmte Visual Basic 6.0-Anwendung ist.

Die Möglichkeiten umfassen das unveränderte Beibehalten einer Visual Basic 6.0-Anwendung, das Migrieren der gesamten Anwendung zu .NET oder das Verwenden der Visual Basic Fusion-Methode. Jede dieser Möglichkeiten stellt in bestimmten Situationen die geeignete Lösung dar.

Unverändert beibehalten

Bei dieser Möglichkeit entscheiden Sie sich dafür, eine Anwendung, die in Visual Basic 6.0 geschrieben wurde, einfach als Visual Basic 6.0-Projekt beizubehalten und .NET Framework überhaupt nicht zu verwenden.

Vorteile:

Problemlos: Die Anwendung wurde in Visual Basic 6.0 geschrieben (oder wurde zu Visual Basic 6.0 migriert), daher ist es am einfachsten, sie unverändert beizubehalten. Wahrscheinlich kennen Ihre Entwickler diese Sprache und Entwicklungsumgebung bereits und können viele Änderungen oder Fehlerbehebungen an der Anwendung schnell vornehmen.

Nachteile:

Hinzufügen neuer Funktionalität: Visual Studio 6.0 wurde 1998 veröffentlicht und seitdem, mit Ausnahme von Service Packs, nicht verbessert. Die Funktionalität, die von heutigen Anwendungen erwartet wird, hat sich jedoch geändert. Von Anwendungen wird erwartet, dass sie automatisch aktualisiert werden, wenn eine neue Version erhältlich ist, dass sie offline eingesetzt werden können, Daten im lokalen Cache speichern, dass sie Internetfunktionalität beinhalten, gegebenenfalls mit Webdiensten kommunizieren und mehr. Es gibt heutzutage zwar die Technologie, um diese Aufgaben zu erleichtern, doch sie ist nicht in Visual Basic 6.0 verfügbar. Es kann also äußerst arbeitsintensiv sein, diese Art von Verbesserungen lediglich mit Visual Basic 6.0 vorzunehmen. Das Endergebnis ist, dass viele Visual Basic 6.0-Anwendungen einfach nicht um diese Art von neuer Funktionalität erweitert werden, weil es zu teuer und schwierig ist, dies nur mit Visual Basic 6.0 zu erreichen.

Fluchtpunkt: Seit der Einführung von Visual Basic .NET in 2002 sind viele Entwickler von Visual Basic 6.0 zu Visual Basic .NET übergegangen. Dementsprechend bildet Visual Basic .NET die Grundlage für die Mehrzahl aller neuen zu Visual Basic zur Verfügung stehenden Informationen (Bücher, Artikel, Blogbeiträge, Newsgroupbeiträge usw.). Gleichzeitig wird die Menge von Informationen, die zu Visual Basic 6.0 verfügbar sind, immer kleiner. Darüber hinaus sind viele Entwickler der Meinung, dass der Wechsel zu Visual Basic .NET ihrer Karriere dienlicher ist, da diese Sprache auch künftig aktualisiert und verbessert wird. Das heißt nicht, dass Sie von nun an nur schwer technische Onlinehilfe für Visual Basic 6.0-Probleme erhalten können oder dass es schwierig ist, einen Visual Basic 6.0-Entwickler zu finden. Langfristig gesehen wird Visual Basic 6.0 jedoch erwartungsgemäß den Weg vieler Legacysprachen einschlagen, sowohl was die verfügbare Informationsfülle als auch die Gruppe von Spezialisten angeht.

Migration zu Visual Basic .NET

Diese Möglichkeit erfordert das vollständige Portieren einer Visual Basic 6.0-Anwendung zu Visual Basic .NET

Vorteile:

Zugriff auf Technologie: Das Migrieren einer Anwendung zu Visual Basic .NET stellt die beste Möglichkeit dar, sicherzustellen, dass Sie aktuelle Innovationen und Technologien schnell integrieren können. Microsoft und andere Unternehmen konzentrieren sich verstärkt auf Funktionalität für .NET Framework. Das bedeutet, dass neue SDKs .NET-Sprachen bevorzugen und möglicherweise nur noch mit diesen arbeiten werden. Neue Technologien wie Webdienste, automatische Aktualisierungen von Anwendungen und Internetfunktionalität (HTTP- und FTP-Unterstützung) sind systemeigen und als solche für .NET-Anwendungen verfügbar. Sie werden jedoch nicht bis zu Visual Basic 6.0 zurückreichen. Sites wie GotDotNet und SourceForge enthalten Tausende von neu verteilbaren Komponenten mit einem Quellcode, der direkt von .NET-Anwendungen aus verwendet werden kann.

Entwicklerproduktivität: Darüber hinaus können neue Versionen von Visual Studio, die ein produktiveres Arbeiten ermöglichen als Visual Studio 6.0, nur mit .NET-Anwendungen verwendet werden.

Nachteile:

Risiko: Das Migrieren einer gesamten Anwendung von Visual Basic 6.0 zu Visual Basic .NET ist keine einfache Sache. Wenn die Anwendung geschäftskritisch ist und die Entwickler keine Erfahrung mit Visual Basic .NET haben, besteht das Risiko, dass die Migration nicht den gewünschten Erfolg hat.

Zeit: Es dauert eine Weile, eine Anwendung zu migrieren und sie so einzurichten, dass sie in .NET genauso funktioniert wie in Visual Basic 6.0. Obwohl das Migrieren der Anwendung eine weitaus bessere Grundlage für zukünftige Verbesserungen bietet, müssen gleichzeitig der Zeit- und Kostenfaktor des Migrierens berücksichtigt werden.

Visual Basic Fusion

Visual Basic Fusion ermöglicht das Verwenden von .NET-Funktionalität von einer Visual Basic 6.0-Anwendung aus.

Vorteile:

Zugriff auf Technologie: Durch das Erstellen von kleinen Visual Basic .NET-Scheibchen können Sie auf die vollständige .NET Framework-Klassenbibliothek zugreifen, Webdienste aufrufen oder Drittanbieter- oder Open Source-.NET-Bibliotheken von Ihren Visual Basic 6.0-Anwendungen aus verwenden.

Geringes Risiko: Der überwiegende Anteil des Anwendungscodes bleibt in Visual Basic 6.0 bestehen und funktioniert unverändert. Der Anteil des Visual Basic .NET-Codes, den Sie schreiben, ist verhältnismäßig klein. Das heißt, dass Sie nicht das Risiko einer fehlgeschlagenen Migration eingehen, weil Sie nicht die gesamte Anwendung migrieren. Außerdem müssen Entwickler, die mit Visual Basic .NET nicht vertraut sind, nur kleine Anteile von .NET Framework lernen, um auf die nötige Funktionalität zuzugreifen.

Hohe Anlagenrendite: Die Investitionskosten sind bei dieser Methode im Vergleich zum Migrieren einer ganzen Anwendung sehr niedrig. Deshalb ist die Anlagenrendite hoch, vor allem kurzfristig gesehen.

Nachteile:

Visual Basic 6.0: Da der Großteil der Anwendung in Visual Basic 6.0 bleibt, ist es erforderlich, dass Sie weiterhin die Visual Basic 6.0-IDE und die Visual Basic 6.0-Sprache verwenden, wenn Sie an der Anwendung arbeiten. Diese Sprache und IDE sind nicht so ergiebig wie Visual Basic .NET.

Debuggen: Um eine Anwendung, die Visual Basic 6.0- und Visual Basic .NET-Code verwendet, wirksam zu debuggen, müssen beide Entwicklungsumgebungen gleichzeitig geöffnet sein, und Sie müssen bestimmte Kenntnisse haben, die erforderlich sind, um eine effektive Fehlerbehebung zwischen Visual Basic 6.0 und Visual Basic .NET durchzuführen.

Wrapperentwicklung: Um auf die .NET-Funktionalität von Visual Basic 6.0 aus zuzugreifen, ist es erforderlich, Wrapper um die .NET-Klassen zu erstellen, damit sie als COM-Objekte verfügbar gemacht werden, die von Visual Basic 6.0 aus verwendet werden können. Diese Wrapper wären nicht erforderlich, wenn Sie die gesamte Anwendung zu Visual Basic .NET migrieren würden.

 

Verwenden des Beispielcodes

Dieser Artikel umfasst einen Beispielcode, der alle besprochenen Themen veranschaulicht. Der Beispielcode wird in einen Ordner namens „Best Practices Code“ extrahiert. Innerhalb dieses Ordners findet sich Folgendes:

  1. Install.bat – Zum Registrieren und Installieren der .NET-Wrapper, sodass sie von Visual Basic 6.0 aus verwendet werden können.

  2. NetFxWrapper – Ordner, der den Quellcode für die Visual Basic .NET-Wrapperklassen enthält.

  3. Best Practices Visual Basic 6 – Ordner, der das Visual Basic 6.0-Beispiel enthält, von dem die Wrapperklasse verwendet wird.

  4. ComClass.zip – Enthält das ComClass-Projektelement. Das Platzieren dieser Datei in Ihrem Ordner C:\Dokumente und Einstellungen\[Benutzername]\Eigene Dateien\Visual Studio 2005\Templates\ItemTemplates macht diese Elementvorlage für Ihre Visual Basic Express-Projekte verfügbar.

Wenn Visual Studio 2005 oder Visual Basic Express nicht installiert sind, können Sie einfach auf install.bat doppelklicken, um die Wrapperklassen zu registrieren. Sie können dann das Visual Basic 6.0-Projekt öffnen, es ausführen und den Code untersuchen, um zu sehen, wie die Wrapper verwendet werden.

Wenn Sie über Visual Studio 2005 oder Visual Basic Express verfügen, können Sie auch den Quellcode für die Wrapperklassen öffnen und untersuchen, wie sie aufgebaut sind.

 

Zusammenfassung

Visual Basic Fusion ist eine nützliche Methode für vorhandene Visual Basic 6.0-Anwendungen, die fortwährend verbessert werden müssen. Mit Visual Basic Fusion können Sie auf eine beliebige Funktionalität zugreifen, die von .NET Framework für Ihre vorhandenen Anwendungen bereitgestellt wird, ohne diese umzuschreiben. Zum Verwenden der Visual Basic Fusion-Methode müssen Sie Visual Basic .NET-Wrapperklassen erstellen, um auf die .NET Framework-Funktionalität zuzugreifen. Das Schreiben dieser Wrapperklassen ist meist problemlos. Dabei müssen jedoch bestimmte Regeln beachtet werden, damit sich die Klassen ordnungsgemäß als COM-Objekte verwenden lassen. In diesem Artikel wurden die Best Practices für das Erstellen von Wrapperklassen behandelt. Außerdem wurden Richtlinien bereitgestellt, mit deren Hilfe Sie entscheiden können, ob Sie Visual Basic Fusion oder eine andere Methode für vorhandene Visual Basic 6.0-Anwendungen verwenden sollten.

 

Der Autor

Scott Swigart (http://www.swigartconsulting.com) verbringt seine Zeit damit, gemeinsam mit Unternehmen Wege zu finden, wie moderne Technologien optimal und zukunftssicher eingesetzt werden können. Er liefert auf diesem Gebiet wertvolle Beiträge zur Visual Basic Fusion-Site, auf der praktische Informationen und Strategien bereitgestellt werden, mit denen VB-Entwickler mit möglichst geringem Aufwand eine umfassende Funktionalität entwickeln können. Scott ist auch Microsoft MVP und Mitautor zahlreicher Bücher und Artikel. Wenn Sie Fragen oder Kommentare zu diesem Artikel haben, senden Sie eine E-Mail an scott@swigartconsulting.com.