我有一个 DLL Com 服务器,实际上只由一个旧的 Delphi exe 应用程序使用。
COM Server 是多年前(不是我)用 C++ ATL 编写的。它实现回调(事件 - 是否相同?) - 使用传出接口IConnectionPointImpl
。类工厂是单例的(标有DECLARE_CLASSFACTORY_SINGLETON
)
现在要求这个 COM 服务器必须在多个客户端之间共享:Delphi 和 C#(.NET 2.0,VS2008)。我把它说成DllSurrogate
现在我可以从多个 Delphi 客户端使用它,使用继承自的类TOleServer
,覆盖GetServer
始终使用的方法CoCreateInstance
(因为GetActiveObject
通常会失败)并且它正在工作。
现在我需要从 C# WinService 使用它,我不知道从哪里开始。我编写了一个使用 WinApi 的小 C# Hello-world,CoCreateInstance
并且DllImport("ole32.dll")
- 我能够从 COM 服务器连接到现有实例,但无法订阅事件。
这是VS导入的DLL META-DATA:
我不知道这是否是正确的方法。这是aproximative代码:
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();
}
}
}
欢迎任何建议、链接和诀窍。