0

Someone know how addhandlers from C# DLL to VB App. When I try to use AddHandler into my VB project, the Visual Studio returns:

Error   BC30676 'DebugMessageEvent' is not an event of 'Debugger'...

The Debugger.Instance.DebugMessageEvent is a part of a DLL called DLLNAMESPACE with his own class called Debugger and send information about the others methods and process from their other classes within DLL called DLLNAMESPACE

enter image description here

If I go to the 'DebugMessageEvent' definition from VB Proj (Auto-Converted from the DLL called DLLNAMESPACE), I get the follow code:

Public Class Debugger
    Public DebugMessageEvent As EventHandler(Of DebugMessageArgs)

    Public Shared ReadOnly Property Instance As Debugger

    Public Class DebugMessageArgs
        Inherits EventArgs

        Public Sub New()

        Public Property Message As Object
    End Class
End Class

The VB Project (Doesn't Work)

Imports DLLNAMESPACE
Public Class myclass
    ...
    Private Sub backup(...)
        AddHandler Debugger.Instance.DebugMessageEvent, AddressOf console_DebugMessageEvent
        ...
    End Sub
    ...
    Private Sub console_DebugMessageEvent(sender As Object, e As Debugger.DebugMessageArgs)
        Console.WriteLine(e.Message)
    End Sub
    ...
End Class

Another C# Project (Works)

using DLLNAMESPACE;
public partial class myclass : Form
{
    ...
    private void backup()
    {
        Debugger.Instance.DebugMessageEvent += console_DebugMessageEvent;
        ...
    }
    ...

    void console_DebugMessageEvent(object sender, Debugger.DebugMessageArgs e)
    {
        Console.WriteLine(e.Message);
    }
    ...
}

enter image description here

The DLL C# Code

using System;
namespace DLLNAMESPACE
{
    public sealed class Debugger
    {
        private static readonly Lazy<Debugger> instance = new Lazy<Debugger>(() => new Debugger());

        private Debugger()
        {

        }

        public static Debugger Instance
        {
            get { return instance.Value; }
        }

        public EventHandler<DebugMessageArgs> DebugMessageEvent;

        public class DebugMessageArgs : EventArgs
        {
            public object Message { get; set; }
        }

        private void RaiseDebugMessageEvent(object message)
        {
            DebugMessageEvent?.Invoke(this, new DebugMessageArgs
            {
                Message = message
            });
        }

        internal void DebugMessage(object data)
        {
            RaiseDebugMessageEvent(data);
        }
    }
}

All the rest of DLL functions works as expected. Please advice, I don't want to change the code of the DLL, just the VB.NET code

Some unsuccessful tests

Pass Visual Studio verification, but others background process associated to DLLNAMESPACE closes.

New EventHandler

Imports DLLNAMESPACE
Public Class myclass
    ...
    Private Sub backup(...)
        Debugger.Instance.DebugMessageEvent = New EventHandler(Of Debugger.DebugMessageArgs)(AddressOf console_DebugMessageEvent)
        ...
    End Sub
    ...
    Private Sub console_DebugMessageEvent(sender As Object, e As Debugger.DebugMessageArgs)
        Console.WriteLine("Consola RoboSharp: " & e.Message)
    End Sub
    ...
End Class

DirectCast

Imports DLLNAMESPACE
Public Class myclass
    ...
    Private Sub backup(...)
        Debugger.Instance.DebugMessageEvent = DirectCast(System.Delegate.Combine(Debugger.Instance.DebugMessageEvent, DirectCast(AddressOf console_DebugMessageEvent, EventHandler(Of Debugger.DebugMessageArgs))), EventHandler(Of Debugger.DebugMessageArgs))
        ...
    End Sub
    ...
    Private Sub console_DebugMessageEvent(sender As Object, e As Debugger.DebugMessageArgs)
        Console.WriteLine("Consola RoboSharp: " & e.Message)
    End Sub
    ...
End Class

If someone have time to recreate my problem, try using robosharp from nuget and add it to your vb.net project

2 Answers2

1

'DebugMessageEvent' is not an event, so you can't treat it as such with 'AddHandler'. It's a field of a delegate type, so you can instead use the following:

Debugger.Instance.DebugMessageEvent = DirectCast(System.Delegate.Combine(Debugger.Instance.DebugMessageEvent, DebugMessage), EventHandler(Of DebugMessageArgs))
Dave Doknjas
  • 6,394
  • 1
  • 15
  • 28
  • I get an error (copy&paste) with Debugger.Instance.DebugMessageEvent = DirectCast(System.Delegate.Combine(Debugger.Instance.DebugMessageEvent, console_DebugMessageEvent), EventHandler(Of Debugger.DebugMessageArgs)) Argument not specified for parameter 'sender' of 'Private Sub console_DebugMessageEvent(sender As Object, e As Debugger.DebugMessageArgs)'. I changed my question with more details Thanks – Elias Rodriguez Pizarro Nov 27 '16 at 20:55
  • @EliasRodriguezPizarro : This works for me: `Debugger.Instance.DebugMessageEvent = DirectCast(System.Delegate.Combine(Debugger.Instance.DebugMessageEvent, DirectCast(AddressOf console_DebugMessageEvent, EventHandler(Of Debugger.DebugMessageArgs))), EventHandler(Of Debugger.DebugMessageArgs))` – Visual Vincent Nov 27 '16 at 22:18
  • @EliasRodriguezPizarro : You have to cast the method as an `EventHandler(Of Debugger.DebugMessageArgs)`. :) – Visual Vincent Nov 27 '16 at 22:19
0

If the Delegate.Combine() solution causes the other applications using the DLL to crash, it seems to me that the best solution would be to create a C# DLL to add the handler for you.

For instance:

using System;

namespace DebuggerHelperDLL
{
    public static class DebuggerHelper
    {
        public static void AddHandler(EventHandler<Debugger.DebugMessageArgs> eventHandler)
        {
            Debugger.Instance.DebugMessageEvent += eventHandler;
        }
    }
}

Then in your VB.NET project:

DebuggerHelper.AddHandler(AddressOf console_DebugMessageEvent)

It seems strange though that it wouldn't work since the compiled C# DLL using the += operator yields this when decompiled into IL:

.method public hidebysig static 
    void AddHandler (
            class [mscorlib]System.EventHandler`1<class DLLNAMESPACE.Debugger/DebugMessageArgs> eventHandler
    ) cil managed 
{
    // Method begins at RVA 0x211c
    // Code size 29 (0x1d)
    .maxstack 8

    IL_0000: nop
    IL_0001: call class DLLNAMESPACE.Debugger DLLNAMESPACE.Debugger::get_Instance()
    IL_0006: dup
    IL_0007: ldfld class [mscorlib]System.EventHandler`1<class DLLNAMESPACE.Debugger/DebugMessageArgs> DLLNAMESPACE.Debugger::DebugMessageEvent
    IL_000c: ldarg.0
    IL_000d: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
    IL_0012: castclass class [mscorlib]System.EventHandler`1<class DLLNAMESPACE.Debugger/DebugMessageArgs>
    IL_0017: stfld class [mscorlib]System.EventHandler`1<class DLLNAMESPACE.Debugger/DebugMessageArgs> DLLNAMESPACE.Debugger::DebugMessageEvent
    IL_001c: ret
} // end of method DebuggerHelper::AddHandler

As you see on offset IL_000d, it calls System.Delegate::Combine():

call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
Visual Vincent
  • 18,045
  • 5
  • 28
  • 75