【问题标题】:VB.NET DLL does not trigger methods in VB6VB.NET DLL 不触发 VB6 中的方法
【发布时间】:2019-07-27 07:28:37
【问题描述】:

我在 VB.NET 中创建了一个 DLL 并在 VB6 中加载。
所有变量和方法都运行良好。

在 DLL 中,我有一个 RaiseEvent
.NET DLL 中的RaiseEvent 无法触发VB6 中的方法。

Option Explicit On
Option Strict On

Imports System.Windows.Forms
Imports System.Net.Sockets
Imports System.IO
Imports System.Text
Imports System.Net
Imports System.ComponentModel
Imports System.Threading
Imports System.Runtime.InteropServices

<ComClass(TestDLL.ClassId, TestDLL.InterfaceId, TestDLL.EventsId)>
Public Class TestDLL
    Public Const ClassId As String = "6E9AB173-14BD-4DE4-9AE0-A9638FCE40B3"
    Public Const InterfaceId As String = "E659D166-F952-489F-899F-0104553B44E4"
    Public Const EventsId As String = "1C38AB4A-84B9-4CC2-A090-0C272177ECED"

    Public Event Disconnected()
    Public Event FirstConnect()
    Public Event Waagerecht()

    Private Sub Received(ByVal msg As String) Handles Me.Receive

     RaiseEvent Waagerecht()

   End Sub

这个 DLL 在 C#、VB.NET 和 Labview 中运行令人惊叹。只是在 VB6 中没有

VB.NET DLL 中的 RaiseEvent 部分

以及VB6中的代码:

Option Explicit

Private WithEvents MyNetClass As TestDll

Private Sub Form_Load()
    Set MyNetClass = New TestDll
End Sub

Private Sub Form_Terminate()
    Set MyNetClass = Nothing
End Sub

以及触发方法:

Private Sub MyNetClass_Waagerecht()
    MsgBox "Ich werde angezeigt, sobald dll mir was sagt"
End Sub

【问题讨论】:

  • 我自己没有尝试在 VB.NET 中编写 COM 可见事件,但我很确定你必须这样做 same thing as in C#
  • 我没有看到明显的东西吗?您的事件在方法 Received 中被触发,但在所示的 VB6 代码中永远不会调用该方法,因此永远不会调用 MyNetClass_Waagerecht(由事件触发)。
  • VB.NET DLL 中的 RaisEvent 应该触发 VB6 中的方法。这部分在VB: NET DLL: Private Sub Received (ByVal msg As String) Handles Me.Receive RaiseEvent Horizo​​ntal() End Sub 并且方法在VB6: Private Sub MyNetClass_Waagerecht() MsgBox "我会尽快显示正如 dll 对我说的那样” End Sub
  • WithEvents MyNetClass 在一个类里面吗?如果不是,我相信 WithEvents 在 VB6 中不起作用。
  • Receive 事件是否到达辅助线程并因此RaiseEvent Waagerecht 在该线程上运行?如果是这样,那可能就是问题所在。使用 Excel VBA 执行此操作时,它似乎可以工作,但 Excel 会在 Dll 上锁定死锁。您可能需要将调用编组回主线程,就像在 WinForms 中使用 Control.InvokeRequired 一样。

标签: vb.net vb6


【解决方案1】:

免责声明:以下内容基于我在使用 Office VBA 时遇到的问题以及在辅助线程上引发的事件。由于它们相似的底层架构,我假设 VB6 也会有类似的问题。我没有 VB6,所以无法验证。

话虽如此,您的代码似乎正在使用NetworkStream.BeginRead,并且回调事件将到达辅助线程,您可能会因为辅助线程上引发的事件而遇到问题。

为了向 COM 类提供线程同步,我使用了System.Windows.Forms.Control。该控件在类构造函数中创建,以捕获创建它的线程。事件被定义为Custom Event,因此RaiseEvent 方法可以定义为使用同步控件的InvokeRequired 属性。我只展示了您的Waagerecht 事件的模式;如果这可行,您将需要为您的其他 Public 事件实现相同的模式。

Private synch As ISynchronizeInvoke

Public Sub New()
    Dim marshalingControl As New System.Windows.Forms.Control
    marshalingControl.CreateControl() ' the handle must be created

    synch = marshalingControl
End Sub

Private _Waagerecht As Action
Public Custom Event Waagerecht As Action
    AddHandler(value As Action)
        _Waagerecht = CType([Delegate].Combine(_Waagerecht, value), Action)
    End AddHandler

    RemoveHandler(value As Action)
        _Waagerecht = CType([Delegate].Remove(_Waagerecht, value), Action)
    End RemoveHandler

    RaiseEvent()
        If _Waagerecht IsNot Nothing Then
            If synch.InvokeRequired Then
                synch.Invoke(_Waagerecht, {})
            Else
                _Waagerecht.Invoke()
            End If
        End If
    End RaiseEvent
End Event

编辑:调试建议

第一步将以下内容添加到 VB.Net TestDLL 类中。

Public Sub TestWaagerecht()
    RaiseEvent Waagerecht()
End Sub

然后在您的 VB6 代码中,将一个按钮添加到您的表单并在其 Click 处理程序中,调用 MyNetClass.TestWaagerecht。这将验证 VB6 代码是否正在接收事件。

希望这适用于 VB6。尝试设置 VB.Net 项目进行调试。如果项目没有app.config,则添加一个(项目菜单->添加新项->“应用程序配置文件”)。我不知道为什么,但是没有app.Config 文件,断点不会被命中。

接下来转到项目属性->调试选项卡,并将“启动外部程序”设置为指向 VB6 程序。在上面我要求您添加的Sub TestWaagerecht 中添加一个断点。

当您在 VS 中单击“开始”按钮开始调试时,它应该会启动 VB6。现在加载您的 VB6 项目并开始调试它。单击调用TestWaagerecht 的按钮。希望 VS 断点会被击中。如果它被击中,那么一切都很好,您可以开始调试代码以希望找到问题。

【讨论】:

  • 嗨 TnTinMn,不幸的是它不起作用。难道是我的VB6代码错了?这是我的 VB6 代码:Option Explicit Private WithEvents YMcomEvent As YMTCPData Private Sub Form_Load() Set YMcomEvent = New YMTCPData End Sub Private Sub YMcomEvent_Waagerecht() If YMcom.YM_OUTPUT1 = 0 Then OUTPUT1 = 0 If YMcom.YM_OUTPUT2 = 0 Then OUTPUT2 = 0 Parse1 = YMcom.YM_Parse1 Parse2 = YMcom.YM_Parse2 cmbSek.ListIndex = YMcom.YM_SecIndex chkTimeOut.Value = YMcom.YM_TimeOutChecked End Sub
  • @SinanTuzcu,在你的问题中,这个类被命名为 TestDll 并且在你的评论中它被命名为 YMTCPData ;你有两个类还是这只是你的问题和实际代码之间的命名冲突?我认为 VB6 代码本质上没有任何问题。我用一些调试建议编辑了我的答案。试一试,然后报告您的进度。
  • 你好,我在这个方法里放了一个msgbox,只显示MSGBOX。另一部分仍然不起作用编辑:调试建议第一步将以下内容添加到 VB.Net TestDLL 类。 Public Sub TestWaagerecht() RaiseEvent Waagerecht() MSGBOX("Hallo") End Sub
猜你喜欢
  • 1970-01-01
  • 2018-10-14
  • 1970-01-01
  • 2012-11-09
  • 1970-01-01
  • 2021-12-27
  • 1970-01-01
  • 2014-04-19
  • 2019-03-19
相关资源
最近更新 更多