VB 2003/VB6 Interop-Problem [lang!]

06/10/2008 - 18:09 von Armin Zingler | Report spam
Hallo miteinander,

ich hoffe, dieses Mal könnte ihr mir helfen. Leider ist die Sache etwas
undurchsichtig. Also: Ich habe eine Assembly, die ich per COM-Interop einem
VB6-Client zur Verfügung stelle. Der VB6-Client besteht aus einer
Standard-Exe und ein paar ActiveX-DLLs. Bei der Assembly habe ich bei den
öffentlichen COM-Klassen explizit Schnittstellen implementiert und jeweils
GUIDs zugewiesen (per GuidAttribute). Die Assembly ist per regasm.exe
registriert und liegt auch im selben Verzeichnis wie die in VB6 geschriebene
Exe. Alles funktioniert pràchtig.

Nun àndere ich in der Assembly eine unwichtige Implementierung. An den
Schnittstellen àndert sich gar nichts. Ich kompiliere die Assembly erneut.
Rufe ich jetzt die VB6-Exe auf, kommt der Fehler &H80004003: "Der
Objektverweis wurde nicht auf eine Objektinstanz festgelegt.". Der Fehler
hat definitiv nichts mit der gemachten Änderung zu tun.

Um das zu debuggen, lade und starte ich das VB6-Hauptprojekt (Source der
Exe) in der IDE. Es stellt sich heraus, dass der Fehler in einer eigenen
ActiveX-DLL auftritt. Um zu sehen, wo, füge ich diese hinzu (Projektgruppe
in VB6). Starte ich erneut, tritt der Fehler nicht mehr auf. Das ist das
erste, was ich nicht verstehe. Dann teste ich weiter und rufe einen Methode
eines Objekts auf, das in der Assembly liegt. Das funktioinert anstandslos.

Wenn ich, alternativ zur Projektgruppe, das Exe-Projekt in einer VB6-Instanz
und das ActiveX-DLL-Projekt in einer zweiten VB6-Instanz lade und starte,
tritt der Fehler &H80004003 auch nicht auf. Wenn ich jetzt aber die Methode
in der Assembly aufrufe, meldet die VB6-IDE: "Das Objekts des Typs
System.__ComObject kann nicht zu Typ ManagedAssembly.ManagedKlasse
umgewandelt werden." Das verstehe ich auch nicht. Das würde doch bedeuten,
dass sich irgendetwas an den Schnittstellen geàndert hat, seitdem die
ActiveX-DLL zum letzten Mal gegen die COM-Assembly kompiliert wurde. Hat es
sich aber nicht! Dauernd habe ich solche Fehler, obwohl die Kompatibilitàt
strikt eingehalten wurde.

Die Binàrkompatibilitàt wurde eingehalten, alle Schnitstellen sind
unveràndert. Das habe ich alles pingelichst genau beachtet! (Für die, die es
nicht wissen: ich mache das schon seit ein paar Jahren und weiß, worauf ich
zu achten habe.) Die managed Assembly liegt übrigens auch als identische
Kopie im selben Verzeichnis wie die VB6.Exe (und wird dort auch gefunden).

Meine Frage (deswegen diese Gruppe) ist jetzt die bzgl des Fehlers
&H80004002: Wie kann das sein? Ich habe an den Schnittstellen nichts
geàndert. Die Fehlermeldung deutet m.E. auf eine Inkompatibilitàt bei der
Zuweisung hin.

Hier der vereinfachte Code:

VB6-Client:
dim daten as ManagedAssembly.ManagedKlasse
If g_Managed.Show(Daten, Ok) Then

Deklaration der Funktion 'Show' in der managed Assembly:

<STAThread()> _
Public Function Show( _
ByRef Daten As ManagedAssembly.ManagedKlasse , _
ByRef ok As Boolean) As Boolean

Der Code in der Methode Show wird gar nicht angerührt, d.h. es scheint
wirklich eine Typ-Inkompatibilitàt, also ein Zuweisungsproblem beim CCW zu
sein. Ich habe nàmlich auch folgendes gemacht: 1. Assembly in VS 2003
geladen, 2. In den Projekteigenschaften als zu startende Exe die VB6.exe
angegeben, 3. Haltepunkt in erster Zeile der Show-Funktion gesetzt, 4.
Projekt gestartet (Startet die VB6.exe), 5. Hauptpprojekt in VB6-IDE
geladen, gestartet und Fehler provoziert. Der Haltepunkt in der Assembly
wird erwartungsgemàß nicht erreicht.

Jetzt habe ich die ActiveX-DLL nochmal kompiliert (ist weitherin
"binàrkompatibel" so wie alles andere auch), ebenso nochmal die Haupt.Exe.
Am Verhalten àndert das nichts. Spàtestens jetzt müssten doch eigentlich
wieder alle DLLs wieder gegen die aktuelle Assembly kompiliert worden sein
und keinen Fehler mehr werfen.

Natürlich kann ich auch - mal wieder - neue, inkompatible Versionen, aller
DLLs (in der Praxis 20 Stück) erstellen. Das würde funktionieren, aber das
kann ja nicht die Lösung nach jeder *irrelevanten* Änderung sein.

Ich verstehe das überhaupt nicht mehr: Habe soeben nochmal die Assemblies
kompiliert. Es hat sich inhaltlich *nichts* geàndert. Das einzige, was mir
dazu einfàllt, ist die Versionsnummer der Assembly (1.1.*), die sich bei
jeder Kompilierung àndert. Habe es mal auf eine fest Versionsnummer
eingestellt. Habe die DLLs wieder verteilt und die Haupt.exe nochmal
gestartet: jetzt kommt plötzlich eine "Schutzverletzung" (0xC0000005). Was
hat das denn bitte mit der Versionsnummer der Assembly zu tun?? Ok, nàchster
Versuch: Nochmal alle beteiligten (VB6-)ActiveX-DLLs kompiliert. Natürlich
weiterhin binàrkompatibel. Haupt.exe nochmal gestartet: Fehler tritt nicht
mehr auf. Kann doch gar nicht sein, weil sich weder an den Schnittstellen
noch an der Implementierung der ActiveX-DLLs etwas geàndert hat.

Falls irgendjemand eine leistungsstarke Glaskugel zu verkaufen hat, bitte
her damit! Ich zahle auch fast jeden Preis! ;-)


Armin
 

Lesen sie die antworten

#1 Jens Gerber
06/10/2008 - 20:55 | Warnen spam
Hallo Armin,

ich kann jetzt leider nicht sagen warum dies so ist,
aber das Verhalten kenne ich.

Die VB Classic exe und evtl. die ActiveX Dll müssen
auf jeden Fall ebenfalls neu kompiliert werden und u.U. die .NET Dll per
regasm
neu registriert. Dann làuft es auf alle Fàlle wieder.
Das kann man auch im Programm automatisiert ausführen.

Ich vermute es liegt an der Versionsnummer der .NET
Assembly, denn die wird ja per regasm für COM registriert.
Es reicht nicht aus die .NET Assembly neu zu erstellen.

Jens

Ähnliche fragen