Windows 7 中 VB6 的 .NET COM 问题:事件不起作用
Posted
技术标签:
【中文标题】Windows 7 中 VB6 的 .NET COM 问题:事件不起作用【英文标题】:.NET COM Issues with VB6 in Windows 7: Event doesn't work 【发布时间】:2013-06-07 15:06:12 【问题描述】:我有一个 Visual Basic 6 使用的 .NET COM DLL。但是,CloseEvent 在 Windows 7 中不起作用,并且抛出了以下异常。 VB6进程调用Init方法没有问题。只有 CloseEvent 不起作用。 Init 和 CloseEvent 在我的 XP 中都可以正常工作。
System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: Object does not match target type. (Fault Detail is equal to An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
System.Reflection.TargetException: Object does not match target type.
at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters)
at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
at FMStation.VbComGateway.IVbComEventGateway.CloseEvent()
at FMStation.VbComGateway.VbComGateway.TriggerCloseEvent()
at FMStation.VbComGateway.VbComGateway.<.ctor>b__0(Object o, EventArgs e)
at FMStation.VbComGateway.VbService.CloseApplication()
at SyncInvokeCloseApplication(Object , Object[] , Object[] )...).
代码如下。这个 COM 对象有一个 Init 方法和一个 CloseEvent 事件。
.NET
public interface IVbComGateway
void Init(string namedPipieId);
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("EA9C2EFC-7A13-4944-9901-29263F4F4B32")]
[ComVisible(true)]
public interface IVbComEventGateway
[DispId(1)]
void CloseEvent();
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IVbComEventGateway))] //Our event source is IMathEvents interface
[ComDefaultInterface(typeof(IVbComGateway))]
public class VbComGateway : IVbComGateway
[ComVisible(false)]
public delegate void MyEventHandler();
private readonly VbService vbService;
private ServiceHost host;
public event MyEventHandler CloseEvent;
public VbComGateway()
vbService = new VbService();
vbService.ClosingApplicationSignalReceived += (o, e) => TriggerCloseEvent();
public void Init(string namedPipieId)
host = new ServiceHost(vbService, new[] new Uri("net.pipe://localhost/" + namedPipieId) );
host.AddServiceEndpoint(typeof(IVbService), new NetNamedPipeBinding(), "PipeReverse");
host.Open();
private void TriggerCloseEvent()
if (CloseEvent != null)
CloseEvent();
在 VB6 中,我使用 WithEvents 来连接这个事件:
Dim WithEvents gateway As FmsVbComGateway.VbComGateway
Private Sub gateway_CloseEvent()
CloseApplication
Dim number As Integer
For number = 0 To VB.Forms.Count - 1
Unload VB.Forms(number)
Next number
End Sub
希望有人可以提供帮助。谢谢!
【问题讨论】:
对我来说就像一个 DLL Hell 问题,在 COM 中总是存在。为该接口提供一个 [Guid] 并且在更新 DLL 时不更改它确实是调用 DLL Hell 的好方法。使用 SysInternals 的 ProcMon 检查该 VB6 应用程序是否正在加载预期的 DLL。 我很确定 DLL 是由 VB6 加载的,因为调用了 Init。此外,上述异常是由 VB6 应用程序创建的 COM 对象 VbComGateway 引发的。 1) DLL 是否已注册?如果注册 64x,则存在一些细微差别。如果这是 32x DLL,则必须使用 c:\Windows\syswow64 文件夹中的 regsvr32。 2) 我假设 XP 是 32x 而 Windows 7 是 64x?确保调用应用程序以 32x 模式运行(针对 x86 编译)。 【参考方案1】:问题终于解决了。我只是在注册 dll,而不是在 Windows 7 机器上注册 tlb。
我正在使用 WIX 创建包。我现在已经将 dll 和 tlb 片段添加到 wxs 脚本(由热生成)来解决这个问题。
【讨论】:
在我的应用程序文件夹中,我必须删除所有 tlb 文件或为当前版本的 dll 生成 tlb 文件。所以当文件夹中的tlb文件与同一文件夹中的dll版本不对应时,问题就存在了。【参考方案2】:这似乎是因为在一般 COM 注册中只注册了 CoClass
和 ComSourceInterfaces
接口。
这只会在某些机器上发生,而在其他机器上完美运行。
目前可行的解决方案是注册 TLB(通过使用 regasm
和 /tlb
参数或在代码中使用 Win32 函数 LoadTypeLibEx
然后 RegisterTypeLib
或 RegisterTypeLibForUser
)
【讨论】:
以上是关于Windows 7 中 VB6 的 .NET COM 问题:事件不起作用的主要内容,如果未能解决你的问题,请参考以下文章
在 Windows 7 / 8 / 10 上安装 VB6 [重复]
Windows 7 上的 VB6 应用程序无法访问映射驱动器
VB6 IDE 是不是在 Windows 7 / 8 / 10 64 位上运行?