VB6 Eigenschaften werden als Methoden konvertiert
-
Mittwoch, 27. Februar 2013 12:40Hallo Gruppe,
in unserem Projekt verwenden wir eine VB6 ActiveX DLL nach wie vor weiter.
Im Projekt wurde eine entsprechende Referenz hinzugefügt.
Nun fiel im Objektbrowser auf dass bestimmte Eigenschaften als set_propname bzw. get_propname Methoden umgesetzt werden.
Auf den Rechnern meiner Kollegen sind die Eigenschaften wie erwartet als Eigenschaften zu verwenden.
Was läuft auf meiner Maschine falsch?
Gruß
HowieD
Alle Antworten
-
Donnerstag, 28. Februar 2013 06:17Moderator
Hallo HowieD,
meine Glaskugel versagt heute ihren Dienst, also kann ich dir nicht sagen, was auf deiner Maschine falsch läuft. Dafür aber einiges über Properties und der Interaktion von verwaltetem mit VB6-Code.
C#-Properties sind einfach syntaktische Abkürzungen für getter/setter-Methoden. Properties werden also vom C#-Compiler immer in get_[Property]()- bzw. set_[Property]()-Methoden übersetzt. Die CLR verwendet zur Laufzeit ausschließlich diese Methoden und kümmert sich kaum um die Metadaten, in denen angegeben wird, dass diese Methoden eigtl. zu einer einzigen Property gehören.
Eine Property wie Point.X erscheint also im IL-Kompilat als:
.property instance int32 X { .get instance int32 System.Drawing.Point::get_X() .set instance void System.Drawing.Point::set_X(int32) }und bei der Ausführung werden direkt get_X() und setX() verwendet:
.method public hidebysig specialname instance int32 get_X() cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: ldfld int32 System.Drawing.Point::x L_0006: ret } .method public hidebysig specialname instance void set_X(int32 'value') cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: ldarg.1 L_0002: stfld int32 System.Drawing.Point::x L_0007: ret }Soweit, so gut. Nun zu COM und VB6. Nehmen wir für den Start folgende VB6-Propertydefinition:
Private m_X As String Public Property Get X() As String X = m_X End Property Public Property Let Name(rhs As String) m_X = rhs End Property
Da der rhs-Parameter des Setters nicht als ByVal deklariert wurde (implizit ByRef also!), würde man in der IDL-Definition der Schnittstelle folgendes finden:
[id(0x...), propget] HRESULT X([in, out] BSTR*);
Das Problem hier sind die [in,out] IDL-Attribute. Ein verwalteter Client wird nicht mehr über instanz.X auf die Property zugreifen können, da keine klare Eingaberichtung vorhanden ist, sondern müsste get_X() bzw. set_X() direkt aufrufen. Und in diesem Fall würde der Code auch problemlos kompiliert werden können. Lösung: Wenn man im VB6-Code ByVal vor rhs einfügt, könnte man im C#-Client wieder über instanz.X auf die Property zugreifen (get_X/set_X wären dann nicht mehr möglich!).
Auf dem Hintergrund dieser Tatsachen kann ich mir z.Z. nur vorstellen, dass auf deiner Maschine eine andere Version der COM-Bibliothek läuft (ohne expliziter ByVal-Angabe), als bei deinen Kollegen. Aber ich lasse mich gern eines besseren belehren.
Gruß
Marcel -
Donnerstag, 28. Februar 2013 08:34
Hallo Marcel,
erst mal Danke für Deine ausführliche Antwort, deren Punkte mir zu größten Teil aber schon bekannt waren.
Hier die Originale Signatur der Eigenschaften aus dem VB6 Klassenmodul:
Public Property Get strConnect() As String strConnect = Connect End Property Public Property Let strConnect(ByVal vNewValue As String) Connect = vNewValue End PropertyWie man sehen kann wurde der Parameter in der Let "Prozedur" ByVal deklariert und trotzdem bekomme ich die get_X/set_X Methoden.
Ich hatte irgendwie gedacht, dass eine oder mehrere Einstellung(en) in VS dieses Verhalten (des TblImp) hervorrufen.
Da wir im Team auch eine SourceCode-Control System verwenden, sollten wir auch auf dem gleichen Codestand arbeiten.
Ist des auch möglich das beim registrieren der COM-DLL etwas anders läuft?Gruß
HowieD -
Donnerstag, 28. Februar 2013 12:02Moderator
Hallo HowieD,
Ich kenne keine tlbimp.exe-Switches, die ein solches Verhalten hervorrufen könnten. Lediglich bei Properties, die Parameter akzeptieren, werden notgedrungen get_X/set_X-Methoden generiert, da es in C# keine parametrisierte Properties gibt (nur Indexer, also Standard-Properties).
Für welche Platform kompilierst Du?
Wie registrierst Du die ActiveX-Bibliothek?
Wie importierst Du die COM-Bibliothek in .NET?
Kannst Du die VB6-DLL und die Interop-Assembly z.B. auf SkyDrive hochladen und hier einen Link posten?
Gruß
Marcel -
Donnerstag, 28. Februar 2013 14:47
Hallo Marcel,
- Platform: VB6 kann ja nichts anderes als 32Bit, daher wir das .NET Projekt als x86 kompiliert.
- Die Registrierung läuft über ein Batch-Script mit folgender Zeile: regsvr32 -s "%curr%Dlls\D4FibuStd.dll"
- Gehe im entsprechenden Projekt auf References/Add Reference und wähle im Bereich COM die entsprechende Komponente aus
- Skydrive Link: würde ich gerne angeben, aber das Forum lässt mich nicht da das Konto noch nicht geprüft sei (andere Möglichkeit?)
Die entscheidenden Eigenschaften befinden sich in "FibuStammdatenClass"Hoffe das bringt uns weiter!
Danke für Deine Hartnäckigkeit!Gruß
HowieD -
Donnerstag, 28. Februar 2013 17:55Moderator
Hallo HowieD,
Den Link kannst Du mir auch zumailen: marcel.roma [at] acm.org. Es wäre nett, wenn Du kein komplettes Projekt sondern nur eine Minimaldemo verlinken könntest (vb6.dll, interop.vb6.dll). Ich werde mir das Ganze morgen ansehen.
Gruß
Marcel

