无法访问 VBA 中的 COM 公开方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10574973/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 16:07:37  来源:igfitidea点击:

Unable to access COM exposed methods in VBA

.netvisual-studio-2008vbacom

提问by peakit

I am trying to access COM exposed methods in VBA.

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

Problem:I am seeing all default methods (like GetHashCode, GetTypeand ToString) in VBA but notthe ones which are part of the COM interface and specifically written to be COM visible (like getStringValue()below).

问题:我在 VBA 中看到了所有默认方法(如GetHashCode,GetTypeToString),但没有看到那些属于 COM 接口并专门编写为 COM 可见的方法(如下getStringValue()所示)。

Set up Details:

设置详情:

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

Interface 'IGetMyString.cs'

接口'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();
    }
}

Implementation 'GetMyString.cs'

实现“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";
        }
    }
}

In Build properties, I checked 'Make Assembly COM Visible'(see below snapshot)

在构建属性中,我选中了“使程序集 COM 可见”(见下面的快照)

enter image description here

在此处输入图片说明

Also asked Visual Studio 2005 to make the 'Register for COM interop'(see below snapshot)

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

enter image description here

在此处输入图片说明

And, finally as a post build event, I am running the regasm.exe to register the .DLL and also the .TLB to registry as follows:

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

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

In Excel Object Explorer view, I enabled COM server (SimpleCOMAssembly written above), and now in the Object Explorer it does not list down the COM interface method (see below) enter image description here

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

Can someone help me know what I am missing which is causing the COM interface methods not show in VBA?

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

EDITAttaching ITypeLib View of the generated TLB enter image description here

编辑附加生成的 TLB 的 ITypeLib 视图 在此处输入图片说明

采纳答案by Hans Passant

The Excel object browser screenshot clearly shows a problem. Note how the GetHashcode, GetType and ToString methods are visible. Those are methods that are inherited from System.Object. But your snippet explicitly (and correctly) uses [ClassInterface(ClassInterfaceType.None)] so that the class implementation is hidden.

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

It isn't hidden. Not so sure how that happened, an old type library from an earlier attempt could explain it. But your build steps are very suspect, you are helping too much. The "Make assembly types COM visible" option is a pretty crude way to force the build system to expose .NET types. But your code is using the refined upper-right-pinky-up-when-you-drink-tea way to expose types to COM. Which includes the [ComVisible(true)] attribute, what the checkbox does, and the [ClassInterface] attribute, which is what the checkbox doesn't do.

它不是隐藏的。不太确定这是怎么发生的,早期尝试的旧类型库可以解释它。但是您的构建步骤非常可疑,您提供的帮助太多了。“使程序集类型 COM 可见”选项是强制构建系统公开 .NET 类型的一种非常粗略的方法。但是您的代码正在使用精致的右上小指在您喝茶时向上的方式向 COM 公开类型。其中包括 [ComVisible(true)] 属性、复选框的作用以及 [ClassInterface] 属性(复选框不执行的功能)。

So the problem is that you asked the build system to implement twointerfaces. Whatever it inherited from the base class, _Object in your case, plus what it inherited from the declaration, IMyGetString in your case. Which is fine and all quite COM compatible, but VBA isn't a very good COM consumer. It only likes the [Default] interface and that's _Object in your case. Clearly visible from the screenshot.

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

So turn off the "Make assembly COM visible" option.

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

And choose between either a postbuild event that calls Regasm or the "Register for COM interop" checkbox. Doing it both ways just doubles the odds that you don't know why it doesn't work. You only need the postbuild when you need to register the assembly for the 64-bit version of Office.

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

回答by transistor1

For the record - in case anyone else needs this answer - I just had the exact same issue as this (OLEView and everything) and it was driving me nuts. I couldn't figure out what I was doing wrong, because I've created several C# COMs before. I forgot to declare the interface (in this post that would be IGetMyString) as public.

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

Hope this saves someone some time.

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

回答by workingobrien

I was having the same issue. I found this link.

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

Guide to calling a .net library from excelIf I am referencing a TLB file called "Foo.tlb" which has a class called "FooClass" that has public members. You will not be able to see those members because they are built by default with late binding (run-time binding) interface only.

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

You can change your class to have early binding, which will allow for intellisense and the Members of the class to be exposed in the Object browser.

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

C#:

C#:

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

You should be able to see the DoSomething method in the object browser after you implement this change. Note: You will have to deference the dll first.

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