Groups | Blog | Home
all groups > dotnet interop > january 2007 >

dotnet interop : COM InterOp - Interface ?s (Great COM InterOp Links within)



JerryWEC
1/26/2007 11:54:22 AM
Hi all, below is most of my code for my COM InterOp object (For those =
following previous posts - I'm not using Inheritance any longer).

My class Logging is implementing ILogging and exposing LogToFile() and =
LogToScreen(). In the VB6 project the properties are showing up under =
the ILogging interface which is public. Is this the best way to expose =
my "Non-Event" methods (subs, functions, properties) to the COM world =
(VB6)? Are there other options to expose my public methods and =
properties?

Note: The ILoggingEvents interface is used to handle the events of my =
Logging class (ComSourceInterfaces() attribute).=20

<Guid("26014480-5D35-49ed-B83C-1B862BF92517")> _

<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _

Public Interface ILoggingEvents

<DispId(1)> _

Sub LogExitDisplayLoggingWindow()

<DispId(2)> _

Sub LogErrorOccurred(ByVal outEx As Exception)

End Interface

=20

<Guid("542FA6CF-F2C8-46d3-8601-EF370BBEF146")> _

<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _

Public Interface ILogging

Property LogToFile() As Boolean

Property LogToScreen() As Boolean

End Interface

=20

#End Region

=20

<Guid("64439B0F-D1BF-43d7-BCD9-BA908BF2CCF6")> _

<ClassInterface(ClassInterfaceType.None)> _

<ProgId("CLA_Logging.Logging")> _

<ComSourceInterfaces(GetType(ILoggingEvents))> _

Public Class Logging

Implements IDisposable

Implements ILogging

=20

Public Delegate Sub LogExitDisplayLoggingWindowHandler()

Public Delegate Sub LogErrorOccurredHandler(ByVal outEx As =
Exception)

Public Event LogExitDisplayLoggingWindow As =
LogExitDisplayLoggingWindowHandler

Public Event LogErrorOccurred As LogErrorOccurredHandler

=20

Public Sub New()

Try

If m_formInstance Is Nothing Then

m_formInstance =3D New frmLogDisplay()

m_formInstance.ParentLogging =3D Me

End If

Catch ex As Exception

ProcessException(ex)

End Try

End Sub

=20

Public Property LogToFile() As Boolean Implements ILogging.LogToFile

Private Get

Try

Return m_LogToFile

Catch ex As Exception

ProcessException(ex)

End Try

End Get

Set(ByVal value As Boolean)

Try

m_LogToFile =3D value

Catch ex As Exception

ProcessException(ex)

End Try

End Set

End Property

=20

Public Property LogToScreen() As Boolean Implements =
ILogging.LogToScreen

Private Get

Try

Return m_LogToScreen

Catch ex As Exception

ProcessException(ex)

End Try

End Get

Set(ByVal value As Boolean)

Try

m_LogToScreen =3D value

Catch ex As Exception

ProcessException(ex)

End Try

End Set

End Property

=20

'*** Other code not shown.

End Class=20



Note: I'll have to change my event that is using the Exception object. =
I'll probably have to make additional changes as well.



Great Links:



(Part 1)

http://www.15seconds.com/issue/040721.htm



(Part 2)...

http://www.15seconds.com/issue/060309.htm



http://www.codeproject.com/dotnet/cominterop.asp

....(See Part 2)


JerryWEC
1/26/2007 2:39:06 PM
In addition to the two previous questions...

In the VB6 Object browser I can see the ILogging interface and all of =
the methods in the interface. However, when writing code all that is =
seen in intellisense is .Dispose from IDisposable. What do I need to do =
to modify my previous code to see the methods exposed in ILogging?

What about the two events in the ILoggingEvents interface?
JerryWEC
1/26/2007 5:24:34 PM
Hi everyone!

I just figure out one peice of the COM InterOp puzzle... I switched the =
order of my interfaces inside the class definition. I put ILogging =
before IDisposible and not .Dispose() does not show up in the VB6 object =
browser but my other methods do.

Have a great weekend!

wawang NO[at]SPAM online.microsoft.com
1/29/2007 9:13:08 AM
Hi Jerry,

Thank you for sharing the two article links about COM interop.

As you already discovered, the first interface will be the default
interface, and VB6 intellisense only works for the default interface.

I think manually use the attributes instead of ComClass attribute is
preferred if you're concerned about the version compatibility issue that
the ComClass may suffer; since ComClass attribute still generates the
interface on your behalf, explicitly control the interface and DispId
certainly put everything under your control.

In case you haven't read following article, it's worth reading:

http://www.dotnetinterop.com/faq/?q=ClassInterface

Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.

wawang NO[at]SPAM online.microsoft.com
1/29/2007 9:20:48 AM
Hi Jerry,

As for the exception handling, the COM client will get the error message
when an exception is thrown from a method exposed from .NET COM component.
For example:

<Guid("542FA6CF-F2C8-46d3-8601-EF370BBEF146")> _
<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface ILogging
Property LogToFile() As Boolean
Sub Log(ByVal text As String)
End Interface


Public Sub Log(ByVal text As String) Implements ILogging.Log
If String.IsNullOrEmpty(text) Then
Throw New ArgumentException("text cannot be empty")
End If
End Sub


Calling this Log method from VB6 with .Log("") will correctly capture the
error message "text cannot be empty" in Err.

However, this mechanism does have a caveat as described here:

#Interop: Get Seamless .NET Exception Logging From COM Clients Without
Modifying Your Code -- MSDN Magazine, January 2005
http://msdn.microsoft.com/msdnmag/issues/05/01/ExceptionLogging/default.aspx


Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
JerryWEC
1/30/2007 2:17:42 PM
Hi all!

I have another question related to COM InterOp...

I have this one event that was originally designed to sent back an exception
object. Is there anyway to MarshalAs as string the execption object or some
way to send back the ex.Message concatinated with the ex.stacktrace? Or do
I have to change my .net code to accomadate COM?

TIA, JerryM

wawang NO[at]SPAM online.microsoft.com
1/31/2007 3:41:37 AM
Hi Jerry,

MarshalAs attribute will be used to help the marshaler understand what the
native memory layout is supposed to look like. It will not be used to help
concat two strings. Also, the article I mentioned in my last reply clearly
states that getting the stack trace from .NET is tricky.


Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
AddThis Social Bookmark Button