问题 无法从VBA实例化用C#编写的COM对象(VB6确定)


使用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的生产机器上。

更新

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

我打电话的时候 CorBindToCurrentRunTime 从VBA尝试强制加载CLR,有趣的是我得到完全相同 HRESULT (0x80131700) 就像我一样 CreateObject() 在VBA。

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


4435
2017-12-17 18:04


起源

我刚刚完成并尝试重现这一点,它在我的机器上运行良好。希望我能提供更多帮助 - JoshBerke
因为你的机器有Visual Studio等,我打赌。当我有解决方案时,我肯定会在这里发帖。谢谢大家的时间。
@ rc1:很棒...... Sysinternals为另一个节省了一天! :) - Vyas Bharghava


答案:


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

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

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

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

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

问题解决了!


13
2017-12-17 20:55



很好,永远不会猜到 - JoshBerke
明显的解决方案;) - Drejc
你最有可能将这个答案标记为“已接受”。 - Chris Hamons
我不推荐这个, 特别 对于真正部署的应用程序(即,请不要在用户计算机上部署Excel.exe.config文件!)。 Excel是一个您实际上并不“拥有”的共享应用程序主机 - 此配置文件会更改所有托管代码在Excel中的工作方式。这将破坏任何不使用CLR 2.0的托管Excel加载项。您应该能够通过正确的注册(检查对象的CLSID注册表项下的CLR版本)和/或CLR加载填充程序获得相同的效果。 - nitzmahone


安装以下修复程序将解决此问题 http://www.microsoft.com/downloads/details.aspx?FamilyID=1b0bfb35-c252-43cc-8a2a-6a64d6ac4670&displaylang=en


2
2017-07-08 07:27





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对象的引用并使用早期绑定?我认为您可能需要先导出一个类型库,但您应该能够添加一个引用并简单地添加该对象。


1
2017-12-17 19:16



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


这适用于VBA ...我尝试使用Word和Excel 2003(SP3)。

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

如果你在服务器上自动化Excel并通过VBA调用触发这个“互操作”,你就会遇到麻烦:)

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

  1. 确保您拥有适当的.Net框架
  2. 您有Office的最新Service Pack
  3. 尝试确定这是否是权利问题。

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

希望这可以帮助。


0
2017-12-17 18:37



谢谢Vyas。生产机器是的我只是指具有Office和.NET的最终用户机器,但没有Visual Studio等。它是否适用于类似的机器?你能分享一些代码吗?谢谢!


rc1是正确的  一个.net错误,当Office无法决定使用哪个版本的Framework时抛出。然而,办公室并没有因为它的选择而受到损害。 Office 2003与.net 2.0的交互方式存在一个错误。

从Microsoft安装修复程序(KB908002)是一种更灵活的解决问题的方法,而不是强制Excel在特定版本的.net中运行。

也可以看看: http://www.biopdf.com/guide/trouble_shoot_microsoft_office_2003.php


0
2017-08-23 15:27