I was doing some research on how to use a certain component we were given as
part of a project. It is a COM object written with ATL; I referenced it via
interop and everything seemed to work perfectly. Until we integrated it
into the main codebase, that is. For some reason the same code would barf on any
call made to a method/property of a legacy ADO Recordset object; an instance of Recordset is passed by reference to the COM object,
which initializes it to certain values. For some reason any call to the Recordset instance after the COM method call would result
in a NullReferenceException being thrown by the
framework.
Oddly enough, tests on the research codebase (on my own machine) now proved
to generate the exact same error; considering I had written and tested the code
merely two days before, I was disinclined to believe the code to be at fault.
Something told me to look into the interop assemblies - we sign every
COM/ActiveX import in the project with our own keyfile using a script which runs
tlbimp/aximp - and reverting to the VS-generated interop
assemblies did indeed resolve the issue. I couldn't find any solution using
Google (a Groups search provided a similar
issue with no solution offered). Finally I stumbled upon the following quote
in this
article:
But
Primary Interop Assemblies have another important use. Interop Assemblies
often need modifications, such as the ones shown in Chapter 7 to be completely
usable in managed code. When you have a PIA with such customizations
registered on your computer, you can benefit from these customizations simply
by referencing the type library for the COM component you wish to use inside
Visual Studio .NET. For example, the PIA for Microsoft ActiveX Data Objects
(ADO), which ships with Visual Studio .NET, contains some customizations to
handle object lifetime issues. If you created your own Interop Assembly for
ADO using TLBIMP.EXE, you would not benefit from these
customizations.
Since the ADO COM object was automatically imported along with our
proprietary objects this got me wondering what sort of "custom optimizations" I
might be missing out on. A quick look in the knowledgebase article on the
ADO PIA
didn't prove very effective (short of a vague statement about "the ADO PIA helps
to avoid certain problems with ADO and .NET COM interoperability") but I decided
to try it out anyway; I removed the preexisting reference from the project,
added "adodb" from the .NET tab in the Add References dialogue (you
could look it up manually in the GAC, but why would you?), fired it up
- problem solved.
As an anecdote, referencing an external library with tlbimp's /reference
command line parameter (particularly the ADODB PIA from the GAC) did not stop it
from generating the imported library anyway. Just go ahead and
delete it.