Calling COM Objects from DOTNET

COM objects raise errors by returning 32-bit HRESULT values. The RCW automatically raises exceptions when it sees a failure HRESULT value. HRESULT values are mapped into the closest corresponding Exception type and are stored in the Exception object as well.

Object Release

The RCW creates a proxy object for each COM object that it wraps. This means that your .NET program deals with a real .NET object that does the work of marshaling method and property calls to the COM object. It holds a reference to the COM object, releasing the COM object when it is no longer needed. But when is that?

As you know, .NET objects are garbage collected and you can't be sure when they'll be finalized. This means that when you use COM objects from .NET, you can't be sure when they will actually be released once you no longer reference the proxy. If the COM object holds resources, you may wish to force a release before you clear your last reference to the object. This can be accomplished using the System.Runtime.InteropServices.Marshal.ReleaseComObject method to decrement the reference count to the COM object. The Marshal class also has an AddRef method to add a reference so you can, in effect, do your own reference counting on the object. Be careful though—incorrect use of these methods can lead to memory leaks or exceptions.

Versioning

You've already read that .NET solves DLL Hell problems by binding assemblies tightly to specific versions of dependent assemblies. Unfortunately, there is no magical way to extend this capability to COM. This means that COM objects called from .NET still potentially suffer from all of the versioning problems that VB programmers have come to know and love. Consider this a reminder to continue your versioning and compatibility discipline even in the unlikely event that your COM objects are only going to be used from .NET assemblies.

Late Binding

The COM interop layer allows for late binding to COM objects. The Type object includes methods GetTypeFromProgID and GetTypeFromCLSID that allow you to obtain a Type object for a COM object and which you can then invoke in a late bound manner.

Marshaling Structures and Other Parameter Types

Most VB programmers are not accustomed to exposing structures (VB6 User types) from ActiveX DLL objects. That's because it was a new feature in VB6 and is both incompatible with older versions of VB (and other platforms) and one of the more unreliable features in the language.[It turns out that marshaling structures to unmanaged code is a rather complex proposition. Other than structures, marshaling of COM parameters and data types to .NET is fairly straightforward, with the exception of variants (which are marshaled into the .NET Object type). Marshaling does potentially become more complex when dealing with non-automation-compatible interfaces but that is a subject (as I mentioned earlier) I won't be covering in this chapter, as VB programmers will rarely face it.

Rather than discuss the problem of structures and other marshaling issues here, I'll cover them in depth later in this chapter when I discuss calling Win32 API functions from .NET. Unlike COM interop where the marshaling process is largely defined by importing and exporting type libraries, with Win32 API calls, you are responsible for defining the marshaling yourself. Once you understand Win32 API marshaling, you'll have no trouble handling any COM marshaling scenarios that may occur.

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish