无法从VBA实例化用C#编写的COM对象(VB6 ok)

11 .net c# com vba com-interop

使用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));
        }       
    }
}
Run Code Online (Sandbox Code Playgroud)

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

REGASM /CODEBASE TESTCOM.DLL
Run Code Online (Sandbox Code Playgroud)

从一个简单的VB6应用程序,这工作正常

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

这个完全相同的代码从Excel中的VBA调用

"自动化错误"(0x80131700)

一切都在开发机器上运行良好,而不是只安装了.NET和MS Office的生产机器上.

更新

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

当我打电话CorBindToCurrentRunTime从VBA,试图强行加载CLR,有趣的是我得到确切同样的HRESULT (0x80131700),当我做CreateObject()在VBA.

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

小智 13

我将回答我自己的问题,希望能让其他人忍受我刚刚忍受的繁琐苦差事.

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

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

<?xml version="1.0"?>
<configuration>
  <startup>
   <supportedRuntime version="v2.0.50727"/>
  </startup>
</configuration>
Run Code Online (Sandbox Code Playgroud)

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

问题解决了!

  • 我不推荐这个,特别是*对于一个真正部署的应用程序(即,请不要在用户计算机上部署Excel.exe.config文件!).Excel是一个您实际上并不"拥有"的共享应用程序主机 - 此配置文件会更改所有托管代码在Excel中的工作方式.这将破坏任何不使用CLR 2.0的托管Excel加载项.您应该能够通过正确的注册(检查对象的CLSID注册表项下的CLR版本)和/或CLR加载填充程序获得相同的效果. (6认同)
  • 明显的解决方案;) (2认同)

Vya*_*ava 0

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

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

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

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

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

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

希望这可以帮助。