无法将COM对象转换为Microsoft.Vbe.Interop.VBE。

3
我是一名有用的助手,可以为您翻译文本。

我有一个用C#编写的COM add-in,在Microsoft Office中运行得非常好。

有一个GitHub问题询问该插件是否支持VB6 IDE。 我需要做什么不同的事情才能让它在Visual Studio 6.0中运行?

以下是相关类列表:

using System;
using Extensibility;
using Microsoft.Vbe.Interop;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Windows.Forms;

namespace Rubberduck
{
    [ComVisible(true)]
    [Guid(ClassId)]
    [ProgId(ProgId)]
    [EditorBrowsable(EditorBrowsableState.Never)]
    //underscores make classes invisible to VB6 object explorer
    //Nothing breaks because we declare a ProgId
    public class _Extension : IDTExtensibility2, IDisposable
    {
        public const string ClassId = "8D052AD8-BBD2-4C59-8DEC-F697CA1F8A66";
        public const string ProgId = "Rubberduck.Extension";

        private App _app;

        public void OnAddInsUpdate(ref Array custom)
        {
        }

        public void OnBeginShutdown(ref Array custom)
        {
        }

        public void OnConnection(object Application, ext_ConnectMode ConnectMode, object AddInInst, ref Array custom)
        {
            try
            {
                // these casts fail when host is VB6 environment
                _app = new App((VBE)Application, (AddIn)AddInInst);
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message, "Rubberduck Add-In could not be loaded", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public void OnStartupComplete(ref Array custom)
        {
            if (_app != null)
            {
                _app.CreateExtUi();
            }
        }

        public void OnDisconnection(ext_DisconnectMode RemoveMode, ref Array custom)
        {
            Dispose();
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing & _app != null)
            {
                _app.Dispose();
            }
        }
    }
}

VBEAddIn类型的强制转换会导致程序崩溃。这个程序集已经注册并且在Office中按照预期运行。

我发现扩展VB6的文档比较难找,但是我的理解是所涉及的接口是相同的——通过附加到VB6进程,在进行强制转换之前中断,并检查Application对象,我可以看到那里的所有成员都符合我预期。

那么为什么它不起作用呢?以下是项目文件中相关的引用:

<Reference Include="extensibility, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
  <EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>

...

<COMReference Include="VBIDE">
  <Guid>{0002E157-0000-0000-C000-000000000046}</Guid>
  <VersionMajor>5</VersionMajor>
  <VersionMinor>3</VersionMinor>
  <Lcid>0</Lcid>
  <WrapperTool>primary</WrapperTool>
  <Isolated>False</Isolated>
  <EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>

我认为问题是,实际上作为“应用程序”传递的是什么。 - RubberDuck
2
@downvoter:不喜欢VB6这个理由就给负评,有点无聊。 - Mathieu Guindon
1
这是一个Office插件,它只能在类似于Excel或Word的Office应用程序中进程内运行。试图从VB6 IDE中使用它是没有意义的,它不像Office应用程序。仍然有一篇古老的KB文章涵盖了在VB6中开发Office扩展。你现有的代码在其中没有任何帮助。 - Hans Passant
2
我对@HansPassant的观点有些怀疑。MZ Tools支持VS6和VBE。http://www.mztools.com/v3/download.aspx - RubberDuck
1个回答

3
问题在于VBA有自己的VBIDE类型库,而VB6也有自己的VBIDE类型库。两个类型库非常相似(尽管VB6版本更丰富),并且都公开了IDTExtensibility2接口。此外,由于IDTExtensibility2是随VB6和Office 2000的VBA 6.x引入的,因此还有针对VB5和我假设的Office 97的VBA 5.x的VBIDE版本,它们公开了原始的IDTExtensibility。
与Hans Passant的答案相反,该插件不是Office插件,而实际上是VBE插件,因此它可以在支持VBA 6/7的任何主机中工作(例如Office、AutoCAD、CorelDraw、SolidWorks等),并且它绝对可以在VB6中工作...只需要多做一些工作。
如果您想支持VB6(或VB5或VBA 5.x),则需要添加对相关Interop程序集的引用,并且在连接时需要转换为适当的类型。
我在 CodeReview 上发布了一个概念验证链接,支持 VB6 和 VBA 6.x\7.x。它远非完整的实现,但你会看到我创建了一个 IVBE 接口来抽象不同的 VBIDE 实现。

Rubberduck VBA 的影响是,IDTExtensibility2 接口 目前 限制了 Rubberduck VBA 对 VBA 6/7 的支持(对于 Office 应用程序而言,这意味着版本为 2000 及更高版本)。 - ThunderFrame
1
MZ Tools 3 之所以有 VB5、VB6 和 VBA 的独立安装程序,也是有原因的。MZ Tools 最初是用 VB6 编写的,由于每个 VBE 类型库都共享相同的名称:VBIDE,因此 VB6 解决方案无法引用多个 VBIDE - ThunderFrame

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接