【问题标题】:Can't instantiate a COM object written in C# from VBA (VB6 ok)无法从 VBA 实例化用 C# 编写的 COM 对象(VB6 ok)
【发布时间】:2010-09-27 09:20:39
【问题描述】:

使用 VS 2008,这是我的 COM 对象

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace TestCom
{    
    [Guid("9E5E5FB2-219D-4ee7-AB27-E4DBED8E123E")]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [ProgId("Test9.COMINT")]
    public class TestComClass  
    { 
        public void Init(string userid, string password)
        {
            MessageBox.Show(string.Format("{0}/{1}", userid, password));
        }       
    }
}

如果我按如下方式构建并在生产机器上注册它

REGASM /CODEBASE TESTCOM.DLL

从一个简单的 VB6 应用程序可以正常工作

Private Sub Form_Load()
  Dim o As Object
  Set o = CreateObject("Test9.COMINT")
  o.Init "A", "B" 
End Sub

在 Excel 中从 VBA 调用的完全相同的代码给出了

“自动化错误”(0x80131700)

在开发机器上一切正常,只是在只安装了 .NET 和 MS Office 的生产机器上不行。

更新

我认为这与在 Excel 下运行时未正确初始化的 .NET 框架有关。如果我使用 Filemon,我可以看到它四处寻找 MSCORWKS.DLL。当我从 VBScript 调用同一个对象时,它发现 MSCorwks.dll 很好。

当我从 VBA 调用 CorBindToCurrentRunTime 以尝试强制加载 CLR 时,有趣的是,我得到的 HRESULT (0x80131700) 与我在 VBA 中调用 CreateObject() 时完全相同。

因此我认为这是一个框架初始化问题。

【问题讨论】:

  • 我刚刚通过并尝试重现它,它在我的机器上也可以正常工作。希望我能提供更多帮助
  • 因为你的机器有 Visual Studio 等,我敢打赌。当我有解决方案时,我一定会在这里发布。谢谢大家的时间。
  • @rc1:太好了... Sysinternals 为另一个人节省了一天! :)

标签: c# .net vba com com-interop


【解决方案1】:

我将回答我自己的问题,希望能让其他人免去我刚刚忍受的单调乏味的苦差事。

如果你得到这个,它因为基于 .NET 的 COM 程序集找不到 .NET 框架

解决方案很简单。创建一个包含以下内容的文件

<?xml version="1.0"?>
<configuration>
  <startup>
   <supportedRuntime version="v2.0.50727"/>
  </startup>
</configuration>

将其命名为“Excel.Exe.Config”并将其放在与“EXCEL.EXE”相同的目录中

问题解决了!

【讨论】:

  • 好人永远猜不到
  • 我不建议这样做,尤其是对于真正部署的应用程序(即,请不要在用户计算机上部署 Excel.exe.config 文件!)。 Excel 是一个您并不真正“拥有”的共享应用程序主机 - 此配置文件更改了所有托管代码在 Excel 中的工作方式。这将破坏任何不使用 CLR 2.0 的托管 Excel 加载项。您应该能够通过正确的注册(检查对象的 CLSID 注册表项下的 CLR 版本)和/或 CLR 加载 shim 获得相同的效果。
【解决方案2】:
【解决方案3】:

RC1,我使用您的 VBScript 代码和 Office 2007 的 Excel 中的代码对此进行了测试,一切正常。

由于您能够从 VB6 表单中创建 COM 对象,我们应该假设您的 .net 框架是正常的。你能排除VBA的问题吗?你能创建一个 .vbs 文件并将其放入其中吗:

Dim o As Object  
Set o = CreateObject("Test9.COMINT")  
o.Init "A", "B"

保存文件并双击它。如果您收到错误,那么我会认为它的注册存在问题,如果您没有收到错误,那么我会查看 Office 和 VBA 并查看是否缺少某些内容或未正确安装。

另一种选择是添加对 COM 对象的引用并使用早期绑定?我认为您可能需要先导出类型库,但您应该能够添加引用并简单地新建对象。

【讨论】:

  • 在 VBScript 中也可以正常工作(需要丢失“作为对象”) 我刚刚在 C# com 对象周围创建了一个 VB6 COM DLL 包装器。 Excel 可以很好地实例化那个 DLL,并调用它自己的方法,但是当那个 VB6 DLL 反过来调用 C# 对象中的方法时,我再次得到“自动化错误”。
  • ...看来问题与 Excel 正在运行有关
【解决方案4】:

这适用于我的 VBA...我使用 Word & Excel 2003 (SP3) 进行了尝试。

我不确定您所说的“生产”机器是什么意思。因为这是一个“客户端”应用程序,必须使用 Excel 在客户端上执行。

如果您要在服务器上自动化 Excel 并通过 VBA 调用触发此“互操作”,那么您就是在自找麻烦 :)

假设通过生产,您的意思是用户将使用 Excel 模板/文档的客户端计算机,这些是以下指针:

  1. 确保您拥有合适的 .Net 框架
  2. 您拥有最新的 Office 服务包
  3. 尝试确定这是否是配股。

如果您喜欢冒险,您可以使用进程资源管理器 [来自 Microsoft sysinternals 网站] 查看加载的 DLL 是什么以及您在哪里遇到错误,并将其与您的开发框上的列表进行比较。

希望这会有所帮助。

【讨论】:

  • 谢谢维亚斯。是的,生产机器我只是指带有 Office 和 .NET 的最终用户机器,但没有 Visual Studio 等。它在类似机器上对您有用吗?您可以分享一些代码吗?谢谢!
【解决方案5】:

rc1 是正确的,因为此 .net 错误,当 Office 无法决定使用哪个版本的框架时抛出。然而,Office 并没有因为选择太多而摇摇欲坠。 Office 2003 与 .net 2.0 交互的方式存在错误。

从 Microsoft (KB908002) 安装修复程序比强制 Excel 在特定版本的 .net 中运行更灵活。

另见:http://www.biopdf.com/guide/trouble_shoot_microsoft_office_2003.php

【讨论】:

    猜你喜欢
    • 2014-08-11
    • 1970-01-01
    • 1970-01-01
    • 2012-03-27
    • 1970-01-01
    • 1970-01-01
    • 2014-07-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多