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

发布于 2024-11-18 17:39:10 字数 1225 浏览 4 评论 0原文

我正在做一个 COM 互操作项目。用 C# 和 .NET Interop 替代一些 VB 和 C++ ATL COM 项目。当我在 .NET 中定义枚举并将它们设置为 ComVisible 时,它​​们会公开为 Typelib.EnumType_EnumValue 而不仅仅是 Typelib.EnumValue。 typelib 导出器这样做是为了确保值名称是唯一的。但我知道我的所有枚举都是唯一的,所以我不需要下划线。如果我不去掉下划线,还有很多客户端代码需要修改。

为了找到这个问题的解决方案,我在 IDL 文件中定义了枚举,并从中创建了一个 typelib 和 .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 公开的程序集引用枚举时,包含对枚举的引用的接口部分将作为受限制的方法公开。

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

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

I'm am doing a COM-interop project. Substituting some VB and C++ ATL COM projects with C# and .NET Interop. When i define enumerations in .NET and they are made ComVisible, they get exposed as Typelib.EnumType_EnumValue enstead of just Typelib.EnumValue. The typelib exporter does this to ensure that the value names are unique. But i know that all my enum's are unique, so i don't want the underscores. Also there is a lot of client code that needs alteration if i don't get rid of the underscores.

To find a solution to this problem, i have defined the enum's in an IDL-file and creating a typelib and .Net interop from this.

[
  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;
};

I create a typelibrary with MIDL.exe which produces a tlb-file.

And i create an assembly with the tlbimp.exe. signing the assembly with the same key as the other Interop assemblies.

tlbimp OpenStructureAdapterEnum.tlb /keyfile:KeyFile.snk

Then i register the assembly with regasm.exe
This assembly looks fine and contains the enum without underscores. But the problem is that a can't see the COM-library from OLE/COM Object Viewer or from VBA or VB6. And when i reference the enum from another COM-exposed assembly, the part of the interface containing references to the enum, gets exposed as resticted methods.

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

How can i create a COM library containing only enums (without underscores) and referencing these from other .net Interop assemblies?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

っ〆星空下的拥抱 2024-11-25 17:39:10

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

Microsoft 提供了一个示例,介绍如何创建没有接口的 TypeLib。它与您所描述的非常相似。您会注意到,其中没有 COM 接口;正因为如此,它必须保持一个低级的 TypeLib。

下一个问题是.NET 程序集。当您使用 TlbImp.exe将枚举导入到您的代码中,这允许您在代码中(在程序集中)使用这些枚举。这是您可以使用枚举执行的操作的限制。您无法导出这些枚举,因为它们不属于您的 .NET 代码。该枚举由 TypeLib 所有。您的 .NET 代码有权使用该枚举,但它不能声明拥有该枚举。

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

To answer your last question first. What you are wanting is a TypeLib not a COM library. Where a COM interface is a bunch of code and function pointers, a TypeLib is the map for interacting with those pointers (along with defines and enums and a bunch of other stuff). Only when they come together is there a COM library. Since there is no COM interface, you cannot have a COM library.

Microsoft has provided an example on how to create a TypeLib without an interface. It is a very similar to the one you have described. As you'll notice, there's no COM interface in it; and because of this, it has to stay a lowly TypeLib.

The next problem is the .NET assembly. When you use TlbImp.exe to import the enums into your code, that allows you to use those enums within your code - inside your assembly. That is the limit of what you can do with the enums. You cannot export those enums because they don't belong to your .NET code. The enum is owned by the TypeLib. Your .NET code has permission to use the enum, but it cannot claim to own the enum.

Finally, to answer your first question. You need to use the features provided with .NET. It has the ability to define enums and export them and make them visible from COM. While I understand the frustration over naming convention, this is not something that you should try to work around or bypass. As you have seen, attempting to bypass this minor problem with the naming convention has caused major problems, effectively making your new code unusable.

祁梦 2024-11-25 17:39:10

我已经这样做了:

在 .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)

I have done this:

In .NET, I created a COM visible library named PermissionControlLib with an enum like this:

public enum NetOperations
{
   Oper1,
   Oper2,
   Oper3
}

In VB6, I've created another enum like this:

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

Usage:

Dim ud as PermissionControlLib.IUser
Set ud = New User
Dim b as Boolean
b = ud.HasPermissionInOperation(VbOperations.Oper1)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文