我有一个(长时间运行的)控制台应用程序,是用C#编写的,我希望能够通过COM操作它(因此没有InProc DLL和regasm.exe)。
IDispatch
这是我所需要的全部,所以是一个经典的OLE自动化对象。
在这里,我将介绍我尝试做的事情的一个最低版本。我定义了如下COM类:
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("9009311a-c0b2-42a4-8e7c-f42091d71594")]
public interface ITestEvents {
void OnEvent();
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[ComSourceInterfaces(typeof(ITestEvents))]
public class ComClass {
public event Action OnEvent;
public int Test() {
return 100;
}
}
在里面
Main()
我只需在运行对象表(ROT)中注册对象
"comTestApp"
命名并休眠应用程序。
您可以查看完整的源代码
here
.
当我尝试调用对象的方法时,这很好。例如,此VBScript工作正常:
Set obj = GetObject("comTestApp")
WScript.Echo obj.Test() Rem prints 100
但当我尝试将事件联系起来时:
Set obj = GetObject("comTestApp")
WScript.Echo obj.Test() Rem Works
WScript.ConnectObject obj, "obj_" Rem Fails
Sub obj_OnEvent
WScript.Echo "Wish it worked"
End Sub
我打电话时出错
ConnectObject
(错误0x80020009“无法连接对象”)。
如果我将程序集注册为regasm的InProc对象,则相同的代码(只需添加类GUID/ProgID)也可以使用。但我不需要那个。我需要访问正在运行的应用程序,这就是我使用ROT的原因。
我创建了一个简单的C++测试,看看是否可以找到有关该问题的更多信息。来源是
here
. 我已经编写了一个最小COM对象来实现
分发接口
应充当事件接收器的接口。首先,我从ROT中获取对象,查询
IConnectionPointContainer
,然后获取
IConnectionPoint
对于
ITestEvents
是IID,最后称其为
Advise()
方法与VBScript一样,它失败了(尽管我收到另一个错误-0x80040202)。我在
QueryInterface
事件接收器的方法,以查看
建议()
被调用。我看得出来
查询接口
为各种接口调用,最后它请求
ITestEvents公司
,返回并设置状态
S_OK
. 但仍然
建议()
方法返回上述错误。
我还尝试了另一件事:我设置了
ITestEvents公司
到
{00020400-0000-0000-C000-000000000046}
这是的IID
分发接口
. 现在呢
建议()
退货
S\u正常
! 我甚至模拟了一个事件
Invoke()
调用事件接收器的方法!唉,总的来说,这并不能解决问题。如果您直接从
I连接点容器
通过IID-你得到了,但它似乎没有被正确地列举出来
ITypeInfo
VBScript仍然无法工作。
我几乎没有COM方面的经验,所以我不知道接下来该怎么办。如果我使用
分发接口
IID让它工作起来,让我想知道
ITestEvents公司
界面,尽管它是纯的
分发接口
所以我认为运行时应该很好地处理它。
非常感谢。