警告MSB3391: <DLL>不包含任何可以用于取消注册COM互操作的类型

12

我使用VS2005制作了一个简单的C# DLL(它是一个更大项目的一部分)。我需要通过VBA代码在Excel中使用该DLL,因此我正在使用程序集上的COM互操作。我正在尝试使构建过程自动生成必要的TLB文件,以便我不需要在每次构建后去命令行并使用regasm。

我的问题是,尽管DLL编译和构建都很顺利,但它没有生成TLB文件。相反,在输出窗口中打印出标题中的错误。

我已经通过进入VS2005中的项目属性 -> 构建 -> 输出 -> 检查“注册COM互操作”来让其他DLL构建TLB文件。还有我在AssemblyInfo.cs中加入了[assembly: ComVisible(true)]。

以下是造成问题DLL源代码和其引用的DLL的返回类型的概述:

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

以下是SymbolTable.dll的摘要,它保存了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*/
    }
}

你为什么需要COM Interop呢?我没有看到任何COM。你是想以后通过COM访问C#程序集吗? - codeulike
1
是的,我需要在Excel VBA中使用这个DLL。 - Rocky
3个回答

27
  1. 您需要有一个无参构造函数。
  2. 你应该在类周围加上GuidAttributeProgIdAttribute
  3. 最好将程序集标记为ComVisible(false),并显式标记需要导出的类。
  4. 使用接口来定义你的类。
  5. 确保程序集级别中有GuidAttribute。

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

3
太棒了,没有任何参数的构造函数解决了问题。非常感谢! - Rocky
空构造函数。这个问题困扰我很久了!谢谢。 - Parrhesia Joe
这对于一个应该在典型的.NET方式中也可用的类来说有点愚蠢。想象一下一个特定的文件格式类,它有一个接受文件名的构造函数 - 在.NET中实例化它的典型方式。现在为了使这个类COM可见,我删除了构造函数,我必须在.NET中调用一个静态的“Load”方法,然后仍然需要一个公共实例/非静态的“Load”方法来为COM创建它。这看起来有点不干净,不是吗? - Ray
注意:对于我来说,直到我将接口和类设置为PUBLIC,错误仍然存在。还要注意,[ProgID]是可选的,[Guid]可以自动生成。 - GilesDMiddleton

4

谢谢提供信息,但我在描述中已经写了我已经有那个了。 - Rocky
我之前已经成功地将其他C# DLLs在COM中运行。虽然这些链接没有帮助我解决我的问题,但我从中了解到了C#中COM客户端智能感知和[ClassInterface(ClassInterfaceType.AutoDual)]之间的联系。谢谢。 - Rocky

3
我看到一个类似的问题,我收到了如下错误: 警告 MSB3391:不包含任何可用于注销 COM 互操作的类型。
我遵循了所有规则(ComVisible 等),但什么都没用。 解决方案:我必须在默认构造函数中放置一些内容,以便它不会被优化掉。一旦有了一些内容,注册就完成了,没有消息,并且组件在注册表中可见。
有趣的是:我的一个朋友在他的机器上(64 位 Windows-7、VS2008-Professional,像我的一样)使用空的默认构造函数成功地注册了原始 DLL。然而,他的 REGASM.EXE 是:
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\regasm.exe 而我的是:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe 因此,这可能是 .NET Framework 版本之间的差异 - 可能较新版本过于优化,REGASM 没有考虑到这一点。

我也收到了这个警告,添加comvisible后寄存器警告消失了,但注销操作直到我在构造函数中加入一个虚拟步骤才成功。 - Justin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接