Question

I've made a simple C# DLL (that's part of a much larger project) using VS2005. I need to use the DLL in Excel via VBA code so I am using COM Interop on the assembly. I am trying to make the build process automatically generate the necessary TLB file so that I don't need to go to the command line and use regasm after every build.

My problem is that although the DLL compiles and builds fine, it does not generate a TLB file. Instead, the error in the title prints out in the output box.

I've gotten other DLLs to build TLB files by going to the project's properties in VS2005 -> Build -> Output -> Check "Register for COM interop". Also I have [assembly: ComVisible(true)] in the AssemblyInfo.cs.

Here's the summary of the source for the problem DLL and the DLL that it references for a return type:

using System;
using System.IO;
using System.Runtime.InteropServices;
using SymbolTable;

namespace ProblemLibrary
{
    public class Foo
    {    
        public Foo(string filename)
        {
            ...
        }

        // method to read a text file into a SymbolTable
        public SymbolTable BuildDataSet(string[] selected)
        {
            ...
        }
    }
}

Here is a summary of SymbolTable.dll. It holds a return type that ProblemLibrary uses.

using System;
using System.Collections.Generic;

namespace SymbolTable
{
    public class SymbolTable
    {
        readonly Dictionary<SymbolInfoStub, string> _symbols = new Dictionary<SymbolInfoStub, string>();

       /*methods that interact with Dictionary snipped*/
    }
}
Was it helpful?

Solution

  1. You need to have ctor without any params.
  2. You should have GuidAttribute and ProgIdAttribute around the classes.
  3. Its better to mark the assembly as ComVisible(false) and mark explicitly the classes that need export.
  4. Use interfaces for your classes.
  5. Make sure the you have GuidAttribute in the assembly level.

    [Guid("<PUT-GUID-HERE-1>")]
    [ComVisible(true)]
    interface IFoo
    {
        void DoFoo();
    }
    
    [Guid("<PUT-GUID-HERE-2>")]
    [ComVisible(true)]
    [ProgId("ProgId.Foo")]
    class Foo : IFoo
    {
        public void DoFoo()
        {
        }
    }
    

OTHER TIPS

I saw a similar problem. I got an error like:

warning MSB3391: does not contain any types that can be unregistered for COM Interop.

I followed all the rules (ComVisible, etc.) but nothing worked.

Solution: I had to put something in the default constructor so that it would not be optimized away. The moment I had something there, the registration finished with no message and the component was visible in the registry.

Interesting note: a friend of mine managed to register the original DLL with the empty default constructor on his machine (64-bit Windows-7, VS2008-Professional, like mine). However, his REGASM.EXE was:

C:\Windows\Microsoft.NET\Framework64\v2.0.50727\regasm.exe

while mine was:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe

So it could be some difference between versions of the .NET framework - maybe the later version is optimizing too much and the REGASM does not account for that.

In the AssemblyInfo.cs file, make sure you have the following:

// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(true)]

UPDATE:

Read: How can I make use of .NET objects from within Excel VBA?

Which links to: http://richnewman.wordpress.com/2007/04/15/a-beginner%E2%80%99s-guide-to-calling-a-net-library-from-excel/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top