创建仅包含枚举的COM库的问题

时间:2011-07-05 06:48:03

标签: .net com interop com-interop idl

我正在做一个COM-interop项目。用C#和.NET Interop代替一些VB和C ++ ATL COM项目。当我在.NET中定义枚举并使它们变为ComVisible时,它们会被公开为Typelib.EnumType_EnumValue,而不仅仅是Typelib.EnumValue。 typelib导出器执行此操作以确保值名称是唯一的。但我知道我的所有枚举都是独一无二的,所以我不想要下划线。如果我没有删除下划线,还有很多客户端代码需要更改。

为了找到这个问题的解决方案,我已经在IDL文件中定义了枚举,并从中创建了一个类型库和.Net互操作。

[
  uuid(64893FD4-359D-46B9-BC1E-48C055796104),
  version(1.0),
  helpstring("ABC"),
  helpfile("AAA.chm"),
  helpcontext(0x00000001)
]

library EnumTypeLib
{
    importlib("stdole2.tlb");
    typedef [uuid(8FF85069-C4E2-4540-A277-4C0F3C19B807), helpstring("MyEnum"), helpcontext(0x00000066)]
    enum MyEnum {
        Value1 = 0,
        Value2 = 1,
    } MyEnum;
};

我使用MIDL.exe创建一个类型库,生成一个tlb文件。

我使用tlbimp.exe创建一个程序集。使用与其他Interop程序集相同的密钥对程序集进行签名。

tlbimp OpenStructureAdapterEnum.tlb /keyfile:KeyFile.snk

然后我用regasm.exe注册程序集 这个程序集看起来很好,包含没有下划线的枚举。但问题是,无法从OLE / COM对象查看器或VBA或VB6中看到COM库。当我从另一个暴露于COM的程序集中引用枚举时,包含对枚举的引用的接口部分将作为resticted方法公开。

[restricted] void Missing7();
[restricted] void Missing8();
[restricted] void Missing9();
[restricted] void Missing10();

如何创建一个只包含枚举(没有下划线)的COM库,并从其他.net Interop程序集中引用它们?

2 个答案:

答案 0 :(得分:1)

首先回答你的上一个问题。你想要的是TypeLib而不是COM库。在COM接口是一堆代码和函数指针的地方,TypeLib是用于与这些指针交互的映射(以及定义和枚举以及一堆其他东西)。只有当他们走到一起时才有一个COM库。由于没有COM接口,因此您无法拥有COM库。

Microsoft提供了有关如何create a TypeLib without an interface的示例。它与您描述的非常相似。你会注意到,它里面没有COM接口;因此,它必须保持低级TypeLib。

下一个问题是.NET程序集。当您使用TlbImp.exe将枚举导入代码时,您可以在代码中使用这些枚举 - 在程序集中。这是你可以用枚举做的限制。您无法导出这些枚举,因为它们不属于您的.NET代码。枚举由TypeLib拥有。您的.NET代码有权使用枚举,但它不能声称拥有枚举。

最后,回答你的第一个问题。您需要使用.NET提供的功能。它能够定义枚举并导出它们并使它们从COM中可见。虽然我理解命名约定的挫败感,但这不是你应该尝试解决或绕过的问题。正如您所看到的,尝试通过命名约定绕过这个小问题已经导致了重大问题,从而有效地使您的新代码无法使用。

答案 1 :(得分:1)

我做到了:

在.NET中,我创建了一个名为PermissionControlLib的COM可见库,其枚举如下:

public enum NetOperations
{
   Oper1,
   Oper2,
   Oper3
}

在VB6中,我创建了另一个这样的枚举:

Public Enum VBOperations
   Oper1=NetOperations.NetOperations_Oper1,
   Oper2=NetOperations.NetOperations_Oper2,
   Oper3=NetOperations.NetOperations_Oper3
End Enum

用法:

Dim ud as PermissionControlLib.IUser
Set ud = New User
Dim b as Boolean
b = ud.HasPermissionInOperation(VbOperations.Oper1)