none
VB6 Eigenschaften werden als Methoden konvertiert

    Allgemeine Diskussion

  • Hallo 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
    Mittwoch, 27. Februar 2013 12:40

Alle Antworten

  • 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 06:17
  • 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 Property
    

    Wie 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 08:34
  • 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 12:02
  • 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 14:47

  • 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

    Donnerstag, 28. Februar 2013 17:55