2009-05-12 56 views
8

He creado una simple C# DLL (que es parte de un proyecto mucho más grande) utilizando VS2005. Necesito usar el DLL en Excel a través del código VBA, así que estoy usando COM Interop en el ensamblado. Estoy tratando de hacer que el proceso de compilación genere automáticamente el archivo TLB necesario para que no necesite ir a la línea de comandos y usar regasm después de cada compilación.advertencia MSB3391: <DLL> no contiene ningún tipo que no se pueda registrar para la Interoperabilidad COM

Mi problema es que, aunque la DLL compila y crea bien, no genera un archivo TLB. En cambio, el error en el título se imprime en el cuadro de salida.

He obtenido otras DLL para compilar archivos TLB yendo a las propiedades del proyecto en VS2005 -> Compilar -> Salida -> Comprobar "Registrarse para interoperabilidad COM". También tengo [assembly: ComVisible (true)] en AssemblyInfo.cs.

Aquí está el resumen de la fuente de la DLL problema y la DLL que hace referencia para un tipo de retorno:

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) 
     { 
      ... 
     } 
    } 
} 

Aquí es un resumen de SymbolTable.dll. Tiene un tipo de devolución que usa ProblemLibrary.

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*/ 
    } 
} 
+0

¿Por qué necesita la interoperabilidad COM? No veo ningún COM allí. ¿Desea acceder al conjunto de C# a través de COM más tarde? – codeulike

+0

Sí, necesito usar esta DLL en Excel VBA. –

Respuesta

18
  1. Necesita tener ctor sin params.
  2. Debe tener GuidAttribute y ProgIdAttribute alrededor de las clases.
  3. Es mejor marcar el conjunto como ComVisible (falso) y marcar explícitamente las clases que necesitan exportarse.
  4. Usa interfaces para tus clases.
  5. Asegúrate de que tienes GuidAttribute en el nivel de ensamblaje.

    [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() 
        { 
        } 
    } 
    
+1

Impresionante, el Constructor sin ningún parámetro fue el truco. ¡Muchas gracias! –

+0

Constructor vacío. ¡Eso me ha estado molestando para siempre! Gracias. –

+0

Eso es un poco tonto para una clase que también debería ser utilizable de la manera típica de .NET. Imagine una clase de formato de archivo específica, que tiene un constructor que acepta un nombre de archivo, una forma típica de instanciarlo en .NET. Ahora solo para hacer que la clase COM sea visible, elimino el constructor y tendré que llamar a un método estático de "carga" para eso en .NET, y luego todavía tengo un método de instancia pública/no-estática "Load" para crearlo solo para COM. Eso se ve un poco sucio, ¿no? –

1

En el archivo AssemblyInfo.cs, asegúrese de tener lo siguiente:

// 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)] 

ACTUALIZACIÓN:

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

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

+0

Gracias por la información, pero escribí en mi descripción que ya la tengo. –

+0

He obtenido otras DLL C# para que funcionen en COM antes. Aunque los enlaces no me ayudaron con mi problema, sí aprendí sobre el vínculo entre el cliente COM intellisense y [ClassInterface (ClassInterfaceType.AutoDual)] en C# a partir de ellos. Gracias por eso. –

2

vi un problema similar. Tengo un error como: MSB3391

advertencia: no contiene ningún tipos que pueden ser registrado para COM Interop .

Seguí todas las reglas (ComVisible, etc.) pero nada funcionó.

Solución: Tuve que poner algo en el constructor predeterminado para que no se optimizara. En el momento en que tuve algo allí, el registro terminó sin mensaje y el componente fue visible en el registro.

Nota interesante: un amigo mío logró registrar la DLL original con el constructor predeterminado vacío en su máquina (Windows-7 de 64 bits, VS2008-Professional, como el mío). Sin embargo, su Regasm.exe era:

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

mientras que el mío era:

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

Así que podría haber alguna diferencia entre las versiones de .NET framework - tal vez la última versión se está optimizando también m uch y el REGASM no cuenta para eso.

Cuestiones relacionadas