2

私は DLL Com サーバーを持っていますが、実際には 1 つの古い Delphi exe アプリケーションでしか使用されていません。

COM サーバーは (私ではなく) 何年も前に C++ ATL で作成されました。コールバックを実装します (イベント - 同じですか?) - 発信インターフェイスを使用しますIConnectionPointImpl。Class Factory はシングルトン ( でマークDECLARE_CLASSFACTORY_SINGLETON)

現在、この COM サーバーを複数のクライアント (Delphi と C# (.NET 2.0、VS2008) の両方) で共有する必要があります。私はそれを入れてDllSurrogate、複数のDelphiクライアントから継承されたクラスを使用して、常に使用するメソッドをTOleServerオーバーライドして(通常は失敗するため)、それを使用できるようになりました。GetServerCoCreateInstanceGetActiveObject

ここで、C# WinService からそれを使用する必要がありますが、どこから始めればよいかわかりません。WinApi を使用する小さな C# Hello-world を作成CoCreateInstanceDllImport("ole32.dll")ました。COM サーバーから既存のインスタンスに接続できますが、イベントをサブスクライブできません。

VS によってインポートされた DLL META-DATA は次のとおりです。 ここに画像の説明を入力

これが正しい方法かどうかはわかりません。近似コードは次のとおりです。

using System;
using System.Collections.Generic;
using System.Text;
using SWLMLib;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;


namespace TestSWLM
{
    [Flags]
    enum CLSCTX : uint
    {
        //... defines here CLSCTX
    }

    class Program
    {
        [DllImport("ole32.dll", EntryPoint = "CoCreateInstance", CallingConvention = CallingConvention.StdCall)]
        static extern UInt32 CoCreateInstance([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
           IntPtr pUnkOuter, UInt32 dwClsContext, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid,
           [MarshalAs(UnmanagedType.IUnknown)] out object rReturnedComObject);

        public static void AboutExpireHandler(IFeature pFeature, int HoursRemained)
        {
            Console.WriteLine("AboutExpireHandler, pFeature = {0}", pFeature.Code);        
        }

        static void Main(string[] args)
        {
            try
            {
                SWLMLib.ISWMgr lintfSWLMgr = null;

                object instance = null;
                UInt32 dwRes = CoCreateInstance(new Guid("8EAAFAD7-73F8-403B-A53B-4400E16D8EDF"), IntPtr.Zero, (uint)CLSCTX.CLSCTX_LOCAL_SERVER,
                    new Guid("00000000-0000-0000-C000-000000000046"), out instance);
                SWLMLib.SWMgrClass lSWLMgr = null;
                unsafe
                {
                    lintfSWLMgr = (instance as SWLMLib.ISWMgr);
                    Type liType = instance.GetType();
                }

                if (lintfSWLMgr != null)
                {
                    IntPtr iuknw = Marshal.GetIUnknownForObject(lintfSWLMgr);

                    IntPtr ipointer = IntPtr.Zero;
                    Guid lICPCGuid = typeof(IConnectionPointContainer).GUID;
                    Guid lICPGuid = typeof(IConnectionPoint).GUID;
                    Guid lIEv = new Guid("{C13A9D38-4BB0-465B-BF4A-487F371A5538}");
                    IConnectionPoint lCP = null;
                    IConnectionPointContainer lCPC = null;
                    Int32 r = Marshal.QueryInterface(iuknw, ref lICPCGuid, out ipointer);
                    lCPC = (IConnectionPointContainer)Marshal.GetObjectForIUnknown(ipointer);
                    lCPC.FindConnectionPoint(ref lIEv, out lCP);
                    Int32 outID;
                    lCP.Advise(???, out outID); // HERE I don't know what to do further
                    lIEvEv.FeatureAboutToExpire += AboutExpireHandler;
                }
            }
            catch (Exception E)
            {
                Console.WriteLine(E.Message);
                throw;
            }

            Console.ReadLine();
        }
    }
}

アドバイス、リンク、ノウハウは大歓迎です。

4

2 に答える 2

0

次のようなコードを書きたいと思うでしょう。

Type type = Type.GetTypeFromCLSID(coClassGuid, true);
object instance = Activator.CreateInstance(type);

これは に似ていると考えることができますCoCreateInstance

C# COM 相互運用の方法は、QueryInterfaceキャストを行うか、次のasキーワードを使用することです。

IComInterface comInterface = instance as IComInterface;

これにより、COM API を直接使用する必要がなくなります。

私は決して COM Interop の専門家ではありません。COM Interop でちょっとした作業をしなければならなかっただけなので、これがお役に立てば幸いです。

于 2013-04-05T17:38:09.427 に答える