Announcement

Collapse
No announcement yet.

COM-Server (Delphi) unter .NET (C#) nutzen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • COM-Server (Delphi) unter .NET (C#) nutzen

    Wir haben eine Automations-Server aufgesetzt und wollen ihn unter .NET (C#) nutzen.
    Der COM-Server läßt sich auch anstandslos instanzieren. Ich habe dann auch eins der COM-Events zugewiesen, auch dies funktionierte und das Event wurde ausgelöst. Allerding erhalte ich bei der Zuweisung des zweiten COM-Events (und dabei ist es egal in welcher Reihenfolge und welches Event ich auslöse) eine Exception, wenn ich den Client starte.

    Anbei sind der .Net Client und der Automations-Server als zip-file

    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;

    namespace TestCOMAddServer
    {
    /// <summary>
    /// Summary description for WinForm.
    /// </summary>
    public class WinForm : System.Windows.Forms.Form
    {
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.Container components = null;
    private System.Windows.Forms.TextBox tbFirstNumber;
    private System.Windows.Forms.TextBox tbSecondNumber;
    private System.Windows.Forms.Label lFirstNumber;
    private System.Windows.Forms.Label lSecondNumber;
    private System.Windows.Forms.Button bAdd;
    private COMAddServer.COMAddServerClass AddServer = new COMAddServer.COMAddServerClass();

    public WinForm()
    {
    //
    // Required for Windows Form Designer support
    //
    InitializeComponent();

    //
    // TODO: Add any constructor code after InitializeComponent call
    //

    AddServer.BeforAdd += new COMAddServer.ICOMAddServerEvents_BeforAddEventHand ler(BeforAdd);
    // Dies nächste Zeile löst eine Exception
    AddServer.AfterAdd += new COMAddServer.ICOMAddServerEvents_AfterAddEventHand ler(AfterAdd);

    }

  • #2
    Hallo,
    wir haben hier exakt dasselbe Problem.
    In Delphi 7 eine ActiveX-Bibliothek mit einem Automatisierungsobjekt erstellt,
    diesem 2 Events verpasst.

    Hänge ich mich jetzt mit meinem .net 2.0 Client an ein Event an, funktioniert es einwandfrei, will ich mich aber auch für das 2. Event registrieren, kommt eben diese Exception beim Zuweisen des Events.

    Ich habe in Google gesehen, dass dieses Problem wohl sehr verbreitet ist und dass man die .net dll disassemblen soll um den Sink-Helper Class von private auf public zu ändern - dies soll das Problem beheben.
    Dieser steht aber in meiner DLL bereits auf public....

    Wer kann hier helfen?

    Ist dieses Problem unter Delphi 2007 immer noch vorhanden??
    Da dieser Bug bereits mehrere Jahre aufzutreten scheint, muss es doch inzwischen eine Lösung geben!

    Bin für jede Hilfe dankbar!

    Comment


    • #3
      Hier noch der Fehlercode mit dem man auch in Google
      mehr als fündig wird:

      ComException wurde nicht behandelt
      HRESULT: 0x80040202

      (wobei ich auch gelesen habe dass andere dasselbe Problem mit der Nummer
      0x80040200 haben...)

      Comment


      • #4
        Lösung

        Wer lange sucht.....

        folgende Lösung hat sich bei mir bewährt:

        Im Initialize des COMOBjects von ckSingle auf ckMulti ändern:

        inherited Initialize;
        FConnectionPoints := TConnectionPoints.Create(Self);
        if AutoFactory.EventTypeInfo <> nil then
        FConnectionPoint := FConnectionPoints.CreateConnectionPoint(
        AutoFactory.EventIID, ckMulti, EventConnect)
        else FConnectionPoint := nil;

        Das allein behebt bei mir bereits den Fehler 0x80040202 !
        Jetzt erst kann man feststellen, dass der ComClient bei Zuweisung von mehreren Events immer den vorhergehenden Handler im ComObject überschreibt, also immer nur das zuletzt registrierte Event ausgeführt wird.

        Unter http://www.gekko-software.nl/Delphi/art11.htm findet man eine Anleitung, wie der Code umzubauen ist damit das funktioniert.
        (Abschnitt "Supporting multiple clients").


        Teilweise kann der Fehler 0x80040202 wohl aber auch auf folgendes zurückzuführen sein.

        ......It has been made known to me that a bug in tlbimp.exe (or a .NET COM interop bug, not sure which) makes running this tutorial difficult in VS.NET final.
        Symptoms:
        During the event sink hookups (e.g. m_Messenger.OnMyStatusChange += m_StatusChangeHandler a System.Runtime.InteropServices.COMException with ErrorCode = 0x80040202 will be thrown. For you COM buffs, 0x80040202 is CONNECT_E_CANNOTCONNECT. I’ve been digging deep through the interop assembly generated with tlbimp.exe with no luck; the CIL is correct and logical. So I stumbled on a newsgroup posting about the same issue. Here’s the problem. tlbmp.exe creates a class called <eventname>_SinkHelper. This class implements the COM sink interface, and stores all the delegates used for callback. The problem is, that the class is marked private. When an instance of the class is passed to Advise on the connection point, COM cannot call QueryInterface() on the object (to get IDispatch, since the sink interface is a disp). So, you ask, how do I fix this? Here’s how.

        Solution:
        When you do the steps above to import the COM type library, open a VS.NET command prompt and change to your project’s “obj” directory. Use ildasm.exe to disassembly the “Interop.MessengerAPI.dll” that was generated by tlbimp.exe (e.g. “ildasm /tok /byt interop.messengerapi.dll /out messengerapi.il”). Once this is done, the CIL source code to the interop assembly will be in the il file specified on the command line. Open this file up in an editor, and do a search for “DMessengerEvents_SinkHelper”. You should find two instances of this line that start with “.class”. Change the private attribute on these lines to “public”. Before we reassemble the assembly, we’ll want to remove the reference to the tlb in our project. In our project’s references, right click on “MessengerAPI” and click “delete”. This will prevent the IDE from running tlbimp.exe again and overwriting our “fixed” assembly.
        Now, reassemble with ilasm.exe (e.g. "ilasm /dll /output=interop.messengerapi.dll messengerapi.il"). Once the "fixed" assembly is generated, add a reference to this assembly (in the Add Reference dialog, in the .NET tab, click "Browse" and find this file). That's it! Now rebuild the application and you should be golden.



        Ich hoffe damit kann jeder der dasselbe Problem hat seinen Leidensweg beenden...

        Comment

        Working...
        X