Laden...

C# DLL für VB6 schreiben

Erstellt von hypersurf vor 15 Jahren Letzter Beitrag vor 15 Jahren 4.290 Views
H
hypersurf Themenstarter:in
523 Beiträge seit 2008
vor 15 Jahren
C# DLL für VB6 schreiben

Hi,

ich möchte gerne eine C#-DLL schreiben, die ich dann in VB einbinden kann.
Das Erstellen der Typelib funktioniert problemlos, und diese lässt sich auch in VB einbinden.

Allerdings wird mir meine Testmethode in VB in der Interface-Klasse IVBTest angezeigt, statt in der richtigen Klasse VBTest.
Instanzieren lässt sich die VBTest-Klasse auch nicht (Laufzeitfehler 429).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ClassLibrary1
{
    [Guid("E0BEF3E9-8297-4a69-BEC3-662451A620C2")]
    public interface IVBTest
    {
        string testfunktion(string test);
    }


    [Guid("8ABEFB55-19FA-4902-A9BF-834378F6AD75"),
     ClassInterface(ClassInterfaceType.None),
     ComSourceInterfaces(typeof(IVBTest))]
    public class VBTest : IVBTest
    {
        public VBTest()
        {

        }

        public string testfunktion(string test)
        {
            return test;
        }

    }
}

VB6 läuft auf einem anderen Rechner als die .NET-Entwicklungsumgebung.

Hat jemand eine Idee, was ich falsch mache?

Danke und Gruß

Markus

4.506 Beiträge seit 2004
vor 15 Jahren

Hallo hypersurf,

schau mal hier:
COM-DLL für VB 6
Managed Code/Objekte in Unmanaged Code verwenden
COM -> .NET (remote!)
COM-Objekt erstellen

Ich debnke wenn Du diese Beiträge durch hast inkl. deren beinhalteten Links, und sich dann noch offene Fragen tümmeln, dann kannst Du sie konkreter noch einmal hier stellen.

Das soll nicht unverschämt sein, aber das Thema, "Wie erstelle ich in .NET eine COM-Klasse" ist hier schon oft besprochen worden, und ein konkretes Problem erkenne ich aus Deiner Fragestellung nicht.

Grüße
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

H
hypersurf Themenstarter:in
523 Beiträge seit 2008
vor 15 Jahren

Hallo Norman-Timo,

die Threads habe ich bereits mehrfach gelesen (bzw. mittlerweile könnte man auch studiert sagen).

Ich habe zwei Probleme:

1.) Ich kann die Klasse VBTest in VB6 nicht instanzieren (Laufzeitfehler 429)
2.) Die Klasse VBTest beinhaltet im VB6-Objektkatalog nicht die Funktion "testfunktion". Diese wird mir in VB6 als Teil der Interfaceklasse angezeigt. Meiner Meinung nach dürfte die Interfaceklasse in VB6 gar nicht auftauchen.

Gruß Markus

4.506 Beiträge seit 2004
vor 15 Jahren

Hallo hypersurf,

ich kann das leider hier jetzt nicht ausprobieen, sehe aber z.B. Abweichungen der Attribute für die Klasse und des Interfaces meines vergangenen geposteten Beitrages:
COM -> .NET (remote!)

Hast Du mal versucht die GUIDs und die Attribute von dem VB Template zu übernehmen? Die werden nämlich vom VS automatisch generiert, weil es unter VB.NET ein Template für COM Klassen gibt, das für C# fehlt.

Grüße
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

H
hypersurf Themenstarter:in
523 Beiträge seit 2008
vor 15 Jahren

So funktioniert es jetzt:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;


namespace ClassLibrary1
{
    [Guid("E0BEF3E9-8297-4a69-BEC3-662451A620C2"),
     InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IVBTest
    {
        [DispId(1)] string testfunktion(string test);
        [DispId(2)] int testfunktion2(int a, int b);
    }


    [Guid("8ABEFB55-19FA-4902-A9BF-834378F6AD75"),
     ClassInterface(ClassInterfaceType.AutoDispatch),
     ComSourceInterfaces(typeof(IVBTest))]
    public class VBTest : IVBTest
    {
        public VBTest()
        {

        }

        public string testfunktion(string test)
        {
            return test;
        }

        public int testfunktion2(int a, int b)
        {
            return a + b;
        }

    }
} 

Sehr komisch ist aber, dass die IntelliSense von VB die beiden Funktion nicht anzeigt, die Funktionen aber aufgerufen werden können und auch funktionieren.

3.971 Beiträge seit 2006
vor 15 Jahren

Das Intellisense von VB6 die Funktionen nicht anzeigt, liegt daran, dass VB6 nicht jede COM-Bibliothek (in dem Fall eine DOT NET Assembly) lesen kann. Da es das Problem in mehreren IDEs gibt, gibt es die Möglichkeit, alle COM-Klassen sowie Interfaces mit dem jeweiligen Funktionen als eine Typbibliothek (Endung .tlb) zu exportieren. Dort enthalten sind dann jeweils die entsprechenden Verweise zu den einzelnen Funktionen der Bibliothek. In deiner IDE bindest du statt die COM-Bibliothek anschließend die TLB ein.

Das man eine DispID in DOT NET angeben muss, ist mir auch neu. Normal weißt die CLR eine entsprechende ID jedem öffentlichen Member zu.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

4.506 Beiträge seit 2004
vor 15 Jahren

Hallo zusammen,

Das man eine DispID in DOT NET angeben muss, ist mir auch neu. Normal weißt die CLR eine entsprechende ID jedem öffentlichen Member zu.

Muss man auch nicht. Ich bin mir 100%ig sicher, dass das auch ohne DispID Angabe funktioniert.

Was ich nur nicht verstehe, warum sich die C#'ler so weigern das VB.NET Konzept zu implementieren, indem man einfach das "ComClass"-Attribut verwendet?

Grüße
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

H
hypersurf Themenstarter:in
523 Beiträge seit 2008
vor 15 Jahren

Das Intellisense von VB6 die Funktionen nicht anzeigt, liegt daran, dass VB6 nicht jede COM-Bibliothek (in dem Fall eine DOT NET Assembly) lesen kann. Da es das Problem in mehreren IDEs gibt, gibt es die Möglichkeit, alle COM-Klassen sowie Interfaces mit dem jeweiligen Funktionen als eine Typbibliothek (Endung .tlb) zu exportieren. Dort enthalten sind dann jeweils die entsprechenden Verweise zu den einzelnen Funktionen der Bibliothek. In deiner IDE bindest du statt die COM-Bibliothek anschließend die TLB ein.

Das man eine DispID in DOT NET angeben muss, ist mir auch neu. Normal weißt die CLR eine entsprechende ID jedem öffentlichen Member zu.

Die TBL-Datei habe ich bereits eingebunden. Als es das erste Mal funktioniert hat, hat VB mir auch alles wunderbar angezeigt. Als ich dann eine weitere Funktion hinzugefügt hab, wurden mir in VB keine Funktionen mehr angezeigt. Komischerweise sehe ich im Objektkatalog in VB meine beiden Funktionen als Events.

Gehe ich beim Erstellen der TBL-Datei denn richtig vor?

tlbexp VBtestProjekt.dll /out:VBtestProjekt.tlb
regasm VBtestProjekt.dll /tlb:VBtestProjekt.tlb
gacutil /i VBtestProjekt.dll

Die letzten beiden Schritte wiederhole ich auf dem Client-PC wo VB6 installiert ist.

4.506 Beiträge seit 2004
vor 15 Jahren

Hallo hypersurf,

hast Du zufälligerweise beide Entwicklungsumgebungen gleichzeitig offen (also VS6 und VS2005/2008)?

VS6 ist noch so richtig monolithisch, es "akzeptiert" keine anderen Göttern neben sich. Soll heißen, VS6 liest (anscheinend) beim Starten alle COM Verbindungen aus und diese kann man dann einbinden (auch mit Intellisense).

Ganz empfindlich ist es auch, wenn man den VS6 Debugger verwendet hat. Dann werden COM Instanzen nicht freigegeben, auch wenn das Debuggen beendet wurde. Erst ein Schließen der ganzen IDE gibt die Instanzen frei.

Also mein Tipp zum Ausprobieren:

  • VS6 Schließen
  • VS2005 - COM Klasse kompilieren
  • VS6 wieder aufmachen
  • Aus dem Projekt die COM Verknüpfung entfernen
  • Die COM Verknüpfung wieder reinnehmen

Dann sollte auch das VB6 Intellisense damit zurechtkommen.

Grüße
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

H
hypersurf Themenstarter:in
523 Beiträge seit 2008
vor 15 Jahren

Visual Studio 6 läuft auf einem anderen rechner, als das .NET-Studio.

Die beiden Dateien (die DLL und die TLB) werden im Moment immer Testweise auf den VB6-Rechner kopiert und dort registriert.

Das mit dem Verweis rausnehmen habe ich ausprobiert, nützt leider nichts 🙁

3.971 Beiträge seit 2006
vor 15 Jahren

Ich lass mir die TLB direkt beim registrieren generieren. regasm ... /tlb. Weiß nicht ob das einen unterschied macht.

Als ich dann eine weitere Funktion hinzugefügt hab, wurden mir in VB keine Funktionen mehr angezeigt

Entweder musst du vor dem einbinden der neuen Bibliothek die alte komplett entfernen und anschließend einfügen, oder bei jeder Änderung der Schnittstelle eine neue CLSID für das Interface vergeben (aber nicht automatisch generieren lassen)

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

H
hypersurf Themenstarter:in
523 Beiträge seit 2008
vor 15 Jahren

Nicht automatisch generieren lassen heisst nicht über "GUID erstellen"? Wie soll ich die GUID dann erstellen?

3.971 Beiträge seit 2006
vor 15 Jahren

Nein, immer schön die Guids manuell generieren lassen und in die entsprechende GuidAttribute kopieren.

Wenn du kein GuidAttribute angibst, vergibt der Compiler eine entsprechende Guid für das/die Interfaces. Da das bei jeder Kompilierung geschieht müsstest immer in VB6 die Verweise ändern.

Da ich bis jetzt noch nicht nachträglich ein COM-Interface geändert habe, deshalb meine Idee nach jeder Änderung der entsprechende Schnittstelle eine neue GUID zu vergeben, um VB6 und dem Zielhost beim registrieren über die entsprechenden Änderungen zu informieren.

Ein manuelles deregistrieren oder deinstallieren der alten COM-Bibliothek ist aber auch in diesem Fall sinnvoll (vor dem installieren der neuen Bibliothek), sonst müllst du mit jeder Änderung Windows mehr zu.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

4.506 Beiträge seit 2004
vor 15 Jahren

Hallo zusammen,

eventuell ist es auch ein Problem, wenn die dahinterstehende .NET Assembly immer wieder die selbe Version bekommt.

Ich kann nicht mit 100%iger Sicherheit sagen in wie weit COM Instanzen gecachet werden, und schon gar nicht im Zusammenhang mit gewrappten .NET Assemblies.

Sind die .NET Assemblies im GAC? Dann würde es sich sowieso anbieten bei Änderungen im Code die Versionsnummer der .NET Bibliothek zu erhöhen.

Grüße
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”