VB.Net Com Interop - 将COM事件接收到VBA客户端

时间:2011-03-28 23:58:43

标签: vb.net com-interop

我正在VB.NET中编写COM互操作DLL,我需要将事件暴露给VBA COM客户端。我只是无法绕过这一个。

这是.NET FTP库的COM包装器,所以不要因为我在BytesTransferred事件上引发BytesTransferred事件而感到困惑。

我最好回想一下,这段代码可以工作,但是当我使用对象浏览器时,它无法在COM客户端中显示任何事件。当我尝试将变量WithEvents:

变暗时,它也无法编译
Public Interface IFTP
    Event BytesTransferred(ByVal ByteCount As Long, ByVal RemoteFileName As String)
End Interface

'Here's the relevant part of my class:
Public Interface IFTP
    Event BytesTransferred(ByVal ByteCount As Long, ByVal RemoteFileName As String)
End Interface

Here's the relevant part of my class:

<ClassInterface(ClassInterfaceType.None)> _
    Public Class FTP : Implements IFTP

    Public Sub New()
        'This needed for com interop
    End Sub

    Public Event BytesTransferred(ByVal ByteCount As Long, ByVal RemoteFileName As String) Implements IFTP.BytesTransferred

    Private Sub fCon_BytesTransferred(ByVal sender As Object, ByVal e As EnterpriseDT.Net.Ftp.BytesTransferredEventArgs) Handles fCon.BytesTransferred
        RaiseEvent BytesTransferred(e.ByteCount, e.RemoteFile)
    End Sub

End Class

我也尝试过类似的东西,但我觉得我在这里遗漏了一些东西,因为它没有编译。我看到一个错误,表示我未能为接口IFTP实现Sub BytesTransferred:

Public Delegate Sub BytesTransferredDelegate(ByVal ByteCount As Long, ByVal RemoteFileName As String)

Public Interface IFTP
    <DispId(1)> _
    Sub BytesTransferred(ByVal ByteCount As Long, ByVal RemoteFileName As String)
End Interface

'Here's the relevant part of my class:

<ClassInterface(ClassInterfaceType.None)> _
    <ProgId("MyTestClass.FTP")> _
    <ComSourceInterfaces(GetType(IFTP))> _
Public Class FTP : Implements IFTP
    Public Event BytesTransferred As BytesTransferredDelegate

    Public Sub New()
        'This needed for com interop
    End Sub

    Private Sub fCon_BytesTransferred(ByVal sender As Object, ByVal e As EnterpriseDT.Net.Ftp.BytesTransferredEventArgs) Handles fCon.BytesTransferred
        RaiseEvent BytesTransferred(e.ByteCount, e.RemoteFile)
    End Sub

End Class

1 个答案:

答案 0 :(得分:6)

<强>解决方案:
1)在代码模块的顶部声明Delegate Subs(带参数,如果需要)(如果你使用的话,在你的命名空间内) 2)为您的活动创建一个单独的界面,如下所示。请务必包含IDispatch声明
3)无需在主界面中为您的活动添加任何内容 4)将ComSourceInterfaces声明与您的类声明一起使用 5)在您的课程中,使用“As”声明您的事件以指向您的Delegate Sub

如Hans Passant所述,请务必使用与VB6 / VBA兼容的数据类型。 Long不是兼容的数据类型。

这是我现在可以使用的代码:

Public Delegate Sub BytesTransferredDelegate(ByVal ByteCount As Long, _
                    ByVal RemoteFileName As String)
Public Delegate Sub OnUploaded()

<InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface IFTPEvents
    <DispId(1)> _
    Sub BytesTransferred(ByVal ByteCount As Double, _
                         ByVal RemoteFileName As String)
    <DispId(2)> _
    Sub Uploaded()
End Interface

Public Interface IFTP
    'Subs, Functions, Properties go here
    'No subs, functions, or events need to be declared here
    'to make our events work properly in COM
End Interface

<ComSourceInterfaces(GetType(IFTPEvents)), ClassInterface(ClassInterfaceType.None)> _
Public Class FTP : Implements IFTP
    Public Event BytesTransferred As BytesTransferredDelegate
    Public Event Uploaded As OnUploaded

    Public Sub New()
        'This needed for com interop
    End Sub

    Private Sub fCon_BytesTransferred(ByVal sender As Object, ByVal e As EnterpriseDT.Net.Ftp.BytesTransferredEventArgs) Handles fCon.BytesTransferred
        RaiseEvent BytesTransferred(e.ByteCount, e.RemoteFile)
    End Sub

    Private Sub fCon_Uploaded(ByVal sender As Object, ByVal e As EnterpriseDT.Net.Ftp.FTPFileTransferEventArgs) Handles fCon.Uploaded
        RaiseEvent Uploaded()
    End Sub

End Class

以下是我用来解决这个问题的来源:
http://msdn.microsoft.com/en-us/library/dd8bf0x3%28v=VS.90%29.aspx
http://www.codeproject.com/KB/COM/cominterop.aspx#UnmanagedSinks
http://www.developerfusion.com/tools/convert/csharp-to-vb/