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

时间:2012-05-13 20:28:12

标签: .net visual-studio-2008 vba com

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

问题:我在VBA中看到了所有默认方法(例如GetHashCodeGetTypeToString),但那些是COM接口的一部分,专门写成COM可见(如下面的getStringValue())。

设置详细信息:

  • Visual Studio 2008
  • Windows 7 x64
  • Office 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";
        }
    }
}

在构建属性中,我选中了' Make Assembly COM Visible' (参见下面的快照)

enter image description here

还要求Visual Studio 2005制作'注册COM互操作(见下面的快照)

enter image description here

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

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

在Excel对象资源管理器视图中,我启用了COM服务器(上面写的SimpleCOMAssembly),现在在对象资源管理器中它没有列出COM接口方法(见下文) enter image description here

有人可以帮助我知道我错过了什么导致COM接口方法无法在VBA中显示?

修改 附加ITypeLib生成的TLB的视图 enter image description here

4 个答案:

答案 0 :(得分:4)

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

它并不隐藏。不太确定如何发生这种情况,来自早期尝试的旧类型库可以解释它。但是你的构建步骤非常可疑,你正在帮助太多。 "使装配类型COM可见"选项是一种非常粗糙的方法,可以强制构建系统公开.NET类型。但是你的代码使用精致的右上角 - 小时 - 你喝 - 茶的方式来向COM公开类型。其中包括[ComVisible(true)]属性,复选框的作用以及[ClassInterface]属性,这是复选框无法执行的操作。

所以问题是你要求构建系统实现两个接口。无论它从基类继承,在你的情况下是_Object,再加上它从你的情况下的声明继承的IMyGetString。这很好,并且完全兼容COM,但VBA并不是一个非常好的COM消费者。它只喜欢[Default]界面和你的情况下的_Object。从屏幕截图中可以清楚地看到。

关闭"使组件COM可见"选项。

在调用Regasm的后期构建事件或"注册COM互操作"之间进行选择。复选框。两种方式做到这一点只会使你不知道为什么它不起作用的可能性加倍。当您需要为64位版本的Office注册程序集时,只需要postbuild。

答案 1 :(得分:2)

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

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

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

C#:

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

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

答案 2 :(得分:1)

对于记录 - 如果其他人需要这个答案 - 我只是有完全相同的问题(OLEView和一切),这让我疯了。我无法弄清楚我做错了什么,因为之前我已经创建了几个C#COM。我忘了将界面(在此帖子中IGetMyString)声明为public

希望这能节省一些时间。

答案 3 :(得分:0)

此外,为了方便查看当前 solution 的其他人,您可以在 Visual Studio 中使用其他几种方法。

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

然后我只是添加到我的PUBLIC界面:

[Guid("[some guid]")]

然后转到我的公开课程并添加了以下内容:

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

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

环境:

  • 使用 .NET Framework 4.7.2 版
  • Windows 10