【发布时间】:2013-03-28 05:02:55
【问题描述】:
我有一个 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 CoCreateInstance 和 DllImport("ole32.dll") 的小 C# Hello-world - 我能够从 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();
}
}
}
欢迎提供任何建议、链接和专有技术。
【问题讨论】:
-
您正在寻找“COM Interop” 对该词的快速 Google 搜索将为您提供所需的一切。
-
@RobertHarvey,我整天都在寻找它们——方法太多,或者至少有 2 种:原始(使用 WinAPI)和导入 TLB 包装 COM 类——我不知道哪个好对于我的范围,尤其是 DLL Surrogate
-
如果您有 TLB,这就是要走的路,只需添加添加引用,然后选择 TLB(使用 Visual Studio 添加引用对话框中的 COM 选项卡)。
-
@SimonMourier,你是什么意思?如果
.TLB 文件 - 我没有,我只有 DLL 和 COM-Server 的源...可以生成吗? -
是的,应该是COM对象编译生成的。通常它是从 .IDL 文件生成的。
标签: c# delphi com interop com-interop