0

I have created a DLL in VB.NET and loaded in VB6.
All variables and methods are working very well.

In the DLL, I have a RaiseEvent.
The RaiseEvent from .NET DLL cannot trigger the methods in 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

This DLL is working in C#, VB.NET and in Labview amazing. Only not in VB6

RaiseEvent Part in VB.NET DLL

And the code in 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

And the methods for triggering:

Private Sub MyNetClass_Waagerecht()
    MsgBox "Ich werde angezeigt, sobald dll mir was sagt"
End Sub
  • 3
    I haven't tried writing COM-visible events in VB.NET myself, but I'm pretty sure you'd have to do the [same thing as in C#](https://stackoverflow.com/q/39511528/11683). – GSerg Jul 25 '19 at 19:33
  • Am I not seeing the obvious? Your event gets triggered in method `Received`, but that method is never called in the shown VB6 code, hence `MyNetClass_Waagerecht` never gets called (triggered by the event). – Hel O'Ween Jul 26 '19 at 12:35
  • The RaisEvent in the VB.NET DLL is supposed to trigger the method in VB6. This part is in VB: NET DLL: Private Sub Received (ByVal msg As String) Handles Me.Receive RaiseEvent Horizontal () End Sub And the method is in the VB6: Private Sub MyNetClass_Waagerecht () MsgBox "I'll be shown as soon as dll says something to me" End Sub – Sinan Tuzcu Jul 26 '19 at 12:42
  • Is `WithEvents MyNetClass` inside a class? If not I believe that WithEvents will not work in VB6. – StayOnTarget Jul 26 '19 at 15:21
  • Does the `Receive` event arrive on a secondary thread and thus `RaiseEvent Waagerecht` runs on that thread? If so, that may be the issue. When doing this with Excel VBA, it appears to work, but Excel takes a death lock on the Dll. You may need to marshal the call back to primary thread just like in WinForms with Control.InvokeRequired. – TnTinMn Jul 26 '19 at 17:05

1 Answers1

0

Disclaimer: The following is based on issues I have experienced with Office VBA and events being raised on a secondary thread. Due to their similar underlying architecture, I am assuming that VB6 will have similar issues. I do not have VB6 so I can not verify the this.

With that stated, it appears that your code is using NetworkStream.BeginRead and the callback events will arrive on a secondary thread, you may be experiencing problems due to the event being raised on the secondary thread.

To provide thread synchronization to the COM class, I utilize a System.Windows.Forms.Control. The control is created in the class constructor to capture the thread it is created on. Events are defined as Custom Event so that the RaiseEvent method can be defined to use the InvokeRequired property of the synchronizing control. I have only shown the pattern for your Waagerecht event; if this works, you will need to implement the same pattern for your other Public events.

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

Edit: Recommendations For Debugging

A first step add the following to the VB.Net TestDLL class.

Public Sub TestWaagerecht()
    RaiseEvent Waagerecht()
End Sub

Then in your VB6 code, add a button to your form and in its Click handler, call MyNetClass.TestWaagerecht. This will verify whether or not the VB6 code is receiving the event.

Hopefully this will work with VB6. Try setting up VB.Net project for debugging. If the project does not have an app.config, add one (Project Menu->Add New Item->"Application Configuration File"). I don't know why, but without the app.Config file, break-points are not hit.

Next go to Project Properties->Debug Tab and set the "Start External Program" to point to the VB6 program. Add a break-point in the Sub TestWaagerecht that I asked you to add above.

Debug Tab

When you click on the "Start" button in VS to start debugging, it should launch VB6. Now load your VB6 project and start debugging it. Click on the button that calls TestWaagerecht. Hopefully, the VS break-point will be hit. If it is hit, then all is well and you can start debugging your code to hopefully find the issue.

TnTinMn
  • 11,522
  • 3
  • 18
  • 39
  • Hi TnTinMn, Unfortunately it does not work. Can it be that my VB6 code is wrong? Here is my VB6 Code: `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` – Sinan Tuzcu Jul 26 '19 at 22:10
  • @SinanTuzcu, In your question, the class is named TestDll and in your comment it is named YMTCPData ; do you have two classes or is this just a naming conflict between your question and actual code? I see nothing inherently wrong with the VB6 code. I have edited my answer with some debugging suggestions. Give those a try and report back with your progress. – TnTinMn Jul 26 '19 at 23:34
  • Hi, I have put a msgbox in this method Only the MSGBOX is displayed. another part is still not works Edit: Recommendations For Debugging A first step add the following to the VB.Net TestDLL class. Public Sub TestWaagerecht() RaiseEvent Waagerecht() MSGBOX("Hallo") End Sub – Sinan Tuzcu Jul 27 '19 at 12:04