VBA - ActiveX 无法为具有依赖项的 .net dll 创建对象

VBA - ActiveX Cant Create Object for .net dll with dependencies

我编写了一个 .Net 库,它封装了一些需要与遗留系统交互的业务逻辑。该库的目的是公开一个 COM 接口,以便我可以使用 VBA.

从 Office 应用程序调用它

我已经完成了使用 64 位 Regasm.exe 和 /codebase /tlb 标志注册它所需要做的一切。它在我的 Office 应用程序中可见,甚至在智能感知中显示。但是,我不断收到 "ActiveX Component cant create object" 错误。

为了尝试确定我的 setup/configuration COM 接口是否有错误,我创建了一个单独的 .Net 库作为我的解决方案的一部分,其中只有一个基本的 class 和 return一个"Hellow World"。这实际上按预期工作,即我在 VBA 应用程序的引用对话框中注册它并可以实例化它和 运行 "HelloWorld" 方法。

Dim simple as SimpleInterface.MyClass
Set simple = New SimpleInterface.MyClass

MsgBox simple.HelloWorld("Say Hello")

然后我在我的新基本 VS 项目中引用我想要的项目(业务逻辑)并调用此处的一个方法,然后在我的简单项目中创建另一个方法以公开为 COM 接口。我注销了dll并按照上面的方法注册。

在我的 VBA 应用程序中,然后我取消选择 .tlb 文件,将其关闭,然后重新打开它,然后重新引用它,然后尝试 运行 代码。这是我得到 "ActiveX componenent can't create object" 的时候。我假设这与我项目中的依赖 dll 有关,但我不确定,因为错误的细节很少。

我不确定我应该在这里做什么?我是否需要注册所有其他依赖的 dll,即我有大约 2 或 3 个外部 dll,我只是在 VS 项目中引用它们?有人能告诉我如何找到更多详细信息吗,即哪个是确切的违规 dll?

"ActiveX Component can't create object" 错误通常意味着定位程序集或其依赖项之一时出现问题,或者程序集不包含任何具有请求的 ProgID 的 public class .要获得有关程序集加载故障排除的更多详细信息,我建议使用 Assembly Binding Log Viewer.

一些要检查的东西

  • 所以您实际上使用的是 64 位版本的 MS Office? (我的印象是 32 位版本仍然是最常用的版本,因为 64 位和 32 位版本之间关于文件 formats/limitations 之类的东西不兼容 Excel文档,但也许情况不再如此...?)
  • 你编译Visual Studio项目时选择了哪个目标平台?
  • 是否曾在项目设置中勾选 "Register for COM Interop" 复选框编译项目?

我要说的是:是否有 任何 可能你实际上 building/registering 错误 platform/bitness(即,与您的 MS Office 安装的位数不匹配)?是否有正确位数的旧注册,这可以解释为什么尽管为错误的目标平台构建,但您仍然在 VBA IDE 的“引用”对话框中看到类型库?

通过 COM 互操作

公开 .NET classes 时要记住的另一件大事

默认情况下,Visual Studio 会在您每次编译项目 时为您公开的 classes 生成新的随机 ProgID GUIDs。这就是为什么在重新编译您的 .NET 项目后,您必须经历删除引用然后将它们重新添加回 VBA IDE 的麻烦,才能使事情再次运行。

不仅如此,它还会用大量过时的键使注册表变得混乱,除非您确保在用新编译的版本覆盖它之前始终注销 (RegAsm /u /tlb) 您的程序集。

为了防止这些事情发生,您应该使用 ProgID attributes on the COM-exposed classes in your .NET code. It is also recommended to use the ComVisible attribute 显式设置 ProgID GUID,并在程序集级别将其设置为 false,并且仅在那些需要暴露给 COM 的类型上显式设置为 true .

关于 .NET 依赖项

您只需将包含 "entry point" 的 DLL 注册到您的组件,即您从 VBA 调用的方法。不过,.NET 运行时需要能够找到依赖项,就像它对任何类型的 .NET 程序集所做的那样。这通常通过将依赖项的副本保存在与入口点 DLL 相同的文件夹中来实现。对于 assembly/project 引用,Visual Studio 通常默认将依赖项复制到输出文件夹,GAC 中存在的程序集除外。

如何使用 Visual Studio 调试器

通过将 Visual Studio 调试器附加到 运行 excel.exe 进程(Debug > Attach to Process 从菜单)。确保 "Managed" 在 Excel 进程的类型列中被提及,并且调试器将附加到它(应该自动发生,除非你已经摆弄了设置)。

如果 Excel 过程中没有提到 "Managed",这意味着 Excel 还没有加载您的程序集;在创建 COM 对象的语句之后尝试 运行 带有断点的 VBA 代码,然后再次尝试附加调试器。

附加 Visual Studio 调试器后,您将可以访问有关正在发生的事情的更多信息。然后,只要抛出 .NET 异常,您就可以让 VS 调试器中断,您还可以添加断点并单步执行 .NET 代码。真的值得研究一下,如果你还没有的话。