Regasm 和 Com Interop 误报

Posted

技术标签:

【中文标题】Regasm 和 Com Interop 误报【英文标题】:Regasm and Com Interop false negatives 【发布时间】:2009-10-30 10:16:20 【问题描述】:

我正在尝试通过 COM 公开我们的库,但似乎是在与工具作斗争而不是实际问题。无论我如何编写我的 COM 公开类,我都会收到警告:“XXX.dll 不包含任何可以为 COM 互操作注册的类型”(在项目属性中将项目标记为注册 COM 互操作)。即使是下面的简单类(作为程序集中唯一使用 ComVisible(false) 签名和标记的类)仍然存在警告:

  [Guid("77699130-7D58-4d29-BE18-385871B000D1")]
  [ComVisible(true)]
  public interface IExample
  
    string GetText();
    void SetText(string text);
  

  [Guid("F91E5EE1-D220-43b5-90D1-A48E81C478B7")]
  [ComVisible(true)]
  public class Example : IExample
  
    private string m_text = "default text";

    public string GetText()
    
      return m_text;
    

    public void SetText(string text)
    
      m_text = text;
    
  

我尝试从命令行运行 regasm,输出很高兴地显示“类型注册成功”。但是,使用 /verbose 开关运行时不会显示任何额外信息(我似乎记得它列出了名称或者可能只是列出了已注册类型的数量)。还尝试使用 /regfile 开关运行 regasm 以生成一个 regfile,该 regfile 会生成以下内容:

[HKEY_CLASSES_ROOT\ComExample.Example]
@="ComExample.Example"

[HKEY_CLASSES_ROOT\ComExample.Example\CLSID]
@="F91E5EE1-D220-43B5-90D1-A48E81C478B7"

[HKEY_CLASSES_ROOT\CLSID\F91E5EE1-D220-43B5-90D1-A48E81C478B7]
@="ComExample.Example"

[HKEY_CLASSES_ROOT\CLSID\F91E5EE1-D220-43B5-90D1-A48E81C478B7\InprocServer32]
@="mscoree.dll"
"ThreadingModel"="Both"
"Class"="ComExample.Example"
"Assembly"="COMInteropTesting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8568e57f6b170d6c"
"RuntimeVersion"="v2.0.50727"

[HKEY_CLASSES_ROOT\CLSID\F91E5EE1-D220-43B5-90D1-A48E81C478B7\InprocServer32\1.0.0.0]
"Class"="ComExample.Example"
"Assembly"="COMInteropTesting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8568e57f6b170d6c"
"RuntimeVersion"="v2.0.50727"

[HKEY_CLASSES_ROOT\CLSID\F91E5EE1-D220-43B5-90D1-A48E81C478B7\ProgId]
@="ComExample.Example"

[HKEY_CLASSES_ROOT\CLSID\F91E5EE1-D220-43B5-90D1-A48E81C478B7\Implemented Categories\62C8FE65-4EBB-45E7-B440-6E39B2CDBF29]

我不是任何衡量标准的 COM 向导,但注册对我来说似乎是有效的。但是,在程序集上运行 regasm 时,注册表中似乎没有出现任何内容。

所以我的问题是我是否在我的简单示例中遗漏了一些东西来进行注册,我是否看到错误的指示,注册是否真的正确,我如何才能更好地确定 COM 注册是否真的有效

编辑: 使用 Kev 建议的更改,我无法避免来自 VS2008 的警告,但实际上我可以直接使用 regasm 在注册表中注册某些内容(仅 VS2008 集成在注册表中没有任何内容)。

然后我尝试删除简单类,所以我有一个空程序集。对此运行 regasm 没有报告任何类型的警告,只报告“类型注册成功”。在我的其他一些可能错误地暴露给 COM 的程序集上运行 RegAsm 时,我看到诸如“RegAsm:警告 RA0000:未注册类型”之类的警告。这是怎么回事,除了注册表和 regasm 的开/关警告之外,我可以信任任何东西吗?

【问题讨论】:

您构建的 Windows 版本是什么? XP、Vista、Win7? 32位/64位? 很遗憾,我没有 XP 的副本来尝试此操作 :(。我无法重现您遇到的问题。 感谢您如此坚持不懈,Kev。对 COM 公开类型的重新引导和重新启动有助于这个简单的示例。尽管如此,仍然在为更大的程序集公开类型而苦苦挣扎。 【参考方案1】:

我根据你的代码创建了一个类库项目,如下:

在项目属性页面中,选择签名选项卡。选中“签署程序集”复选框并从“选择强名称密钥文件:”下拉框中选择 <New...>

然后我添加了以下类(Example.cs)

[Guid("77699130-7D58-4d29-BE18-385871B000D1")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[ComVisible(true)]
public interface IExample

    [DispId(1)]
    string GetText();

    [DispId(2)]
    void SetText(string text);


[Guid("F91E5EE1-D220-43b5-90D1-A48E81C478B7")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class Example : IExample

    private string m_text = "default text";

    [ComVisible(true)]
    public string GetText()
    
      return m_text;
    

    [ComVisible(true)]
    public void SetText(string text)
    
      m_text = text;
    

然后我构建了项目,然后放到命令行中,从构建中输出 DLL。

注册:

regasm.exe COMInteropTesting.dll /register /codebase /tlb

如果您的组件需要可供多个应用程序访问:

gacutil.exe -i COMInteropTesting.dll

这一切在 Windows 2003 32 位、Windows 2008 32 位和 Windows 7 64 位上运行良好。

一个问题是,如果您在 64 位系统上使用 CScript 测试组件,则需要运行正确的 CScript 解释器。如果您使用 32 位 RegAsm.exeC:\Windows\Microsoft.NET\Framework\v2.0.50727)注册了程序集,那么您需要在 c:\Windows\SysWOW64 运行 32 位 CScript 解释器。

【讨论】:

仍然来自 VS2008 的相同警告......叹息......但是,似乎实际上出现在注册表中。希望能更清楚地表明成功。 (附带问题:如果我在 /codebase 注册,是否真的需要将其添加到 gac) 啊...我有一个我们在 GAC 中注册的 COM 组件。那就是说我觉得你的困境很奇怪。 将此标记为答案,因为这将产生一个工作样本

以上是关于Regasm 和 Com Interop 误报的主要内容,如果未能解决你的问题,请参考以下文章

C# COM DLL:我使用 Regasm 还是 Regsvr32?

关于COM .net程序集,regasm,dll,tlb和guids的几个简短问题

在 Excel VBA 中调用没有管理权限的 COM 互操作 regasm

在RegAsm COM dll之后找不到PHP COM文件

Regasm组件注册工具使用方法

no_logic_in_create_state 抽象方法是误报 #2345