8

我正在尝试访问 VBA 中的 COM 公开方法。

问题:我在 VBA 中看到了所有默认方法(如和) GetHashCode,但不是作为 COM 接口一部分且专门编写为 COM 可见的方法(如下所示)。GetTypeToStringgetStringValue()

设置详情:

  • 视觉工作室 2008
  • 视窗 7 x64
  • 办公室 2007
  • .NET 3.5

接口“IGetMyString.cs”

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace SimpleCOMAssembly
{
    [ComVisible(true), GuidAttribute("4153A1AC-ECE9-4f66-B56C-1DDEB6514D5D")]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    interface IGetMyString
    {
        [DispId(1)]
        string getStringValue();
    }
}

实施“GetMyString.cs”

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace SimpleCOMAssembly
{
    [ComVisible(true), GuidAttribute("0A3D4D65-CF50-4020-BF13-77001F8AAABE")]
    [ProgId("SimpleCOMAssembly.GetMyString")]
    [ClassInterface(ClassInterfaceType.None)]
    public class GetMyString : IGetMyString
    {
        public GetMyString() { }

        [ComVisible(true), Description("Get my string")]
        public string getStringValue()
        {
            return "hello";
        }
    }
}

在 Build 属性中,我选中了“Make Assembly COM Visible”(见下面的快照)

在此处输入图像描述

还要求 Visual Studio 2005 进行“注册 COM 互操作”(参见下面的快照)

在此处输入图像描述

最后,作为构建后事件,我正在运行 regasm.exe 来注册 .DLL 以及 .TLB 到注册表,如下所示:

%SystemRoot%\Microsoft.NET\Framework\v2.0.50727\regasm /codebase "$(TargetPath)" /tlb:"$(TargetDir)$(TargetName).lib"

在 Excel 对象资源管理器视图中,我启用了 COM 服务器(上面写的 SimpleCOMAssembly),现在在对象资源管理器中它没有列出 COM 接口方法(见下文) 在此处输入图像描述

有人可以帮助我知道我缺少什么导致 COM 接口方法未在 VBA 中显示吗?

编辑 附加生成的 TLB 的 ITypeLib 视图 在此处输入图像描述

4

4 回答 4

6

Excel 对象浏览器屏幕截图清楚地显示了一个问题。请注意 GetHashcode、GetType 和 ToString 方法是如何可见的。这些是从 System.Object 继承的方法。但是您的代码段明确(并且正确)使用 [ClassInterface(ClassInterfaceType.None)] 以便隐藏类实现。

它没有隐藏。不太清楚这是怎么发生的,早期尝试的旧类型库可以解释它。但是您的构建步骤非常可疑,您提供的帮助太多了。“使程序集类型 COM 可见”选项是强制构建系统公开 .NET 类型的一种非常粗略的方法。但是您的代码正在使用精炼的右上角-pinky-up-when-you-drink-tea 方式向 COM 公开类型。其中包括 [ComVisible(true)] 属性,复选框的作用和 [ClassInterface] 属性,这是复选框不做的。

所以问题是你要求构建系统实现两个接口。无论它从基类继承什么,在你的例子中是 _Object,加上它从声明中继承的,在你的例子中是 IMyGetString。这很好,并且与 COM 完全兼容,但 VBA 不是一个很好的 COM 使用者。它只喜欢 [Default] 界面,在您的情况下就是 _Object 。从截图中清晰可见。

所以关闭“使程序集 COM 可见”选项。

并在调用 Regasm 的构建后事件或“注册 COM 互操作”复选框之间进行选择。两种方式都这样做只会使您不知道为什么它不起作用的几率增加一倍。只有在需要为 64 位版本的 Office 注册程序集时才需要 postbuild。

于 2012-05-13T20:39:46.403 回答
3

我遇到了同样的问题。我找到了这个链接。

从 excel 调用 .net 库的指南 如果我引用一个名为“Foo.tlb”的 TLB 文件,该文件有一个名为“FooClass”的类,该类具有公共成员。您将无法看到这些成员,因为默认情况下它们仅使用后期绑定(运行时绑定)接口构建。

您可以将您的类更改为具有早期绑定,这将允许智能感知和类的成员在对象浏览器中公开。

C#:

[ClassInterface(ClassInterfaceType.AutoDual)]
public class FooClass
{
    public FooClass()
    {
    }
    public string DoSomething()
    {
        return "I am printing....";
    }
}

实现此更改后,您应该能够在对象浏览器中看到 DoSomething 方法。注意:您必须首先尊重 dll。

于 2013-01-17T20:34:17.177 回答
2

作为记录 - 如果其他人需要这个答案 - 我只是遇到了与此完全相同的问题(OLEView 和所有内容),这让我发疯了。我不知道我做错了什么,因为我之前创建了几个 C# COM。我忘记将接口(在这篇文章中IGetMyString)声明为public.

希望这可以节省一些时间。

于 2012-11-12T14:57:30.867 回答
0

此外,为了查看当前解决方案的其他人,您可以在 Visual Studio 中使用其他一些方法来解决此问题。

首先,我检查了“使程序集 COM 可见”和“注册 COM 互操作”(在构建选项下)。

然后更进一步,我刚刚添加到我的PUBLIC界面:

[Guid("[some guid]")]

刚刚去了我的公共课并添加了这个:

[Guid("[some other unique guid]")]
[ClassInterface(ClassInterfaceType.None)]

这很有效。如果你做的一切都正确,那么你的编译中应该有一个 dll 和一个 tlb。从那里将它们导入您正在处理的项目中,VB6 将看到并显示所有对象的方法和任何其他公开的值/设置器/获取器,使用这种方法,枚举似乎也可以正常工作。

环境:

  • 使用 .NET Framework 4.7.2 版
  • 视窗 10
于 2021-02-22T21:16:07.580 回答