Reputation: 12230
I'm programming a COM interop DLL in VB.NET and I need the events to be exposed to a VBA COM client. I just can't wrap my head around this one.
This is a COM wrapper for a .NET FTP library so don't get too confused by the fact that I'm raising a BytesTransferred event on a BytesTransferred event.
As I best recall, this code works but simply fails to show any events in the COM client when I use the object browser. It also fails to compile when I try to Dim my variable 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
I've also tried something like this but I think I'm missing something here because it doesn't compile. I see an error that says I've failed to implement Sub BytesTransferred for interface IFTP:
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
Upvotes: 4
Views: 2595
Reputation: 12230
Solution:
1) Declare Delegate Subs (with arguments if needed) at top of code module (inside your namespace if you are using one)
2) Create a separate interface for your events, as shown below. Be sure to include the IDispatch declaration
3) No need to put anything for your events in your primary interface.
4) Use the ComSourceInterfaces declaration with your class declaration
5) Inside your class declare your events using "As" to point to your Delegate Sub
As mentioned by Hans Passant, be sure to use data types that are compatible with VB6/VBA. Long is not a compatible data type.
Here's my code that now works:
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
Here's the sources I used to solve this problem:
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/
Upvotes: 7