gpt4 book ai didi

c# - 在 C# 中处理 VB6 事件 - 为什么它有时只起作用?

转载 作者:行者123 更新时间:2023-12-02 15:42:38 24 4
gpt4 key购买 nike

我有一个作为 ActiveX exe 实现的 VB6 应用程序。我还有一个 C# 应用程序,它通过 COM 与 VB6 应用程序交互。

除一种情况外,这一切都很好。

如果从 C# 应用程序启动 VB6 应用程序,一切都很好。但是,如果 VB6 应用程序已经独立运行,那么尽管 COM 接口(interface)仍然有效,但 C# 事件处理程序永远不会触发。

代码的(非常简化的)摘录如下,更改名称和 GUID 以保护无辜者。

VB6 应用程序:myVB6App.cls (GlobalSingleUse)

Event myEvent()

public function RaiseMyEvent()
RaiseEvent myEvent
end function

(部分)从构建的 VB6 exe 生成的 IDL:

...
[
uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx),
version(1.10),
appobject
]
coclass myApp {
[default] interface _myApp;
[default, source] dispinterface __myApp;
};
...
[
uuid(yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy),
version(1.10),
hidden,
nonextensible
]
dispinterface __myApp {
properties:
methods:
...
[id(0x00000005)]
void myEvent();
...
};
...

C# 应用:

public class myAppInterface : IDisposable, ImyAppEvents
{
public delegate void myEventDelegate();
public event myEventDelegate myEventHandler;
private object _myApp = null;
private IConnectionPoint _connectionPoint;
private int _sinkCookie;

public myAppInterface()
{
_myApp = Activator.CreateInstance(Type.GetTypeFromProgID("myVB6ProjectName.myApp"));
Guid g = new Guid("yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy");
connectionPointContainer.FindConnectionPoint(ref g, out _connectionPoint);
_connectionPoint.Advise(this, out _sinkCookie);
}
public void myEvent()
{
if (myEventHandler != null)
{
myEventHandler();
}
}
}

[ComImport, Guid("yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"), TypeLibType((short)4240)]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
public interface ImyAppEvents
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(5)]
void myEvent();
}

public class myC#App
{
private static myAppInterface _vb6App;
public static myAppInterface VB6Application
{
get
{
if (_vb6App == null)
{
_vb6App = new myAppInterface();
_vb6App.myEventHandler += new myAppInterface.myEventDelegate(DoSomething);
}
return _vb6App;
}
}
static void DoSomething()
{
//code to actually handle the event
}
}

正如我所说,如果在 Activator.CreateInstance 运行时,VB6 exe 当前未运行,则一切都按预期工作并且 DoSomething() 中的代码在 VB6 应用程序中触发 myEvent 时执行。

如果 VB6 应用程序事先独立运行,C# 应用程序仍然可以通过 COM 控制它(为清楚起见,上面未显示方法)但是 DoSomething() 代码永远不会运行以响应 我的事件

有什么地方出错了吗?

最佳答案

我认为问题在于为事件设置接收器。快速猜测一下,我会说您正在创建 VB 组件的新实例并将新接收器分配给该实例生成的事件,而不是分配给已经运行的组件。

VB6 文档指出:

Setting the Instancing property of a class to GlobalMultiUse orGlobalSingleUse allows client programs to use the properties andmethods of the class as if they were global functions, but within theproject where you defined the GlobalMultiUse class module, objectscreated from the class are not global.

这意味着当您尝试连接到一个正在运行的实例时,您实际上得到了 VB6 类的一个新副本,它有自己的事件,而不是已经运行的类。因此没有收到事件。

关于c# - 在 C# 中处理 VB6 事件 - 为什么它有时只起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1577323/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com