Archive for February 2006

Creating the Primary Interops Microsoft left out

As many developers have discovered, if you’ve written a VB6 dll that you decided to use from .NET, and you decided to create primary interops for your DLL(s), then you will encounter a snag. In order to create a primary interop, all of the exposed types also need primary interops. The usual suspects are:

  • ADODB (exposed recordsets)
  • VBA (exposed collections)
  • VBRUN (? not sure)
  • Scripting (Dictionaries, File System Objects)

Microsoft supplies ADODB with VS.NET, so there is no problem there. But the others you will have to create yourself. Here is the Nant script I use to do that:

<target name="PrepareThirdPartyInterops">
<regasm unregister="false" codebase="false" assembly="${build.dir}\ADODB.dll" />
<regasm unregister="false" codebase="false" assembly="${build.dir}\Microsoft.stdformat.dll" />
<regasm unregister="false" codebase="false" assembly="${build.dir}\msdatasrc.dll" />

<gac action="uninstall" failonerror="false">
<assemblies>
<include name="${build.dir}\interop.scripting.dll" />
<include name="${build.dir}\interop.vba.dll" />
<include name="${build.dir}\interop.stdformat.dll" />
<include name="${build.dir}\interop.vbrun.dll" />
</assemblies>
</gac>

<tlbimp typelib="${system32}\scrrun.dll" output="${build.dir}\interop.scripting.dll" asmversion="5.6.0.8820"
namespace="scripting" keyfile="${build.dir}\mykeyfile.snk" primary="true" />

<tlbimp typelib="${system32}\msvbvm60.dll" output="${build.dir}\interop.vba.dll" asmversion="6.0.97.82"
namespace="vba" keyfile="${build.dir}\mykeyfile.snk" primary="true" />

<tlbimp typelib="${system32}\MSVBVM60.DLL\3" output="${build.dir}\interop.vbrun.dll" asmversion="6.0.0.0"
namespace="vbrun" keyfile="${build.dir}\mykeyfile.snk" primary="true">
<references>
<include name="${build.dir}\interop.vba.dll" />
<include name="${build.dir}\Microsoft.stdformat.dll" />
<include name="${build.dir}\msdatasrc.dll" />
</references>
</tlbimp>

<gac action="install">
<assemblies>
<include name="${build.dir}\interop.scripting.dll" />
<include name="${build.dir}\interop.vba.dll" />
<include name="${build.dir}\interop.vbrun.dll" />
</assemblies>
</gac>
</target>

One last note. Microsoft.stdformat.dll and msdatasrc.dll are necessary for vbrun. They are available from Microsoft as part of the Office 2003 Primary Interop download. ADODB is also in there, in case you don’t have it.

ADODB Interop woes

Microsoft supplies a primary ADODB interop that is installed by default with VS.NET 2003 and 2005. You can distribute this interop, and it works ok.

My current project is using this interop simply because we reference some (of our own) COM DLLs that expose ADO recordsets. We generate primary interops for these COM DLLs, to make them simpler to use from our .NET code.

But, on a new build machine, the interops would not generate. They gave an error “Referenced type library ‘ADODB’ does not have a primary interop assembly registered”. Now this was not true! I had ADODB installed in the GAC as well as registered as a primary interop. So what was going on?

Turns out that the interop is only really registered as primary for ADO 2.7. So unless the version of ADO used by the COM DLLs is 2.7, the interop is not recognized. The solution was simple enough, although it took me a while to piece it together:

  1. Go to the registry, to HKEY_CLASSES_ROOT\TypeLib\{00000205-0000-0010-8000-00AA006D2EA4}\2.5
  2. Add a new string key called “PrimaryInteropAssemblyName”
  3. Set the value to “ADODB, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”
  4. Repeat for other versions of ADO that you may be using, (2.0, 2.1, 2.6 on my machine). They are all next to each other in the registry.
  5. Don’t bother going higher than 2.7. I think if your COM DLLs are compiled against 2.8 then you probably wouldn’t have the problem to begin with.

Howto: Register a .TLB file using VB6

There are no built-in tools to register a “.tlb” (type library) file on a Windows computer. However, you can do it with the VB6 IDE as follows:

  1. Create a new VB6 EXE
  2. Add a reference to the TLB file by browsing to it on your hard drive
  3. Run the VB6 EXE from the IDE (don’t skip this step – it is necessary)
  4. Quit the EXE and quit VB (no need to save anything).

The TLB is now registered, and will be available to other VB6 programs. This is the procedure we did on our Nant build machine to allow some of our VB6 apps to compile.