【问题标题】:Visual Basic - invoking .net runtimeVisual Basic - 调用 .net 运行时
【发布时间】:2018-03-23 08:46:11
【问题描述】:

我正在尝试从 VBA (Word/Excel) 的 .net 运行时调用对象。 这有效: oT = CreateObject("System.Text.UTF8Encoding") 但不是这个: CreateObject("System.Management.Automation.Runspaces.RunspaceFactory") 错误是: 运行时错误“429”; ActiveX 组件无法创建对象

我不明白的是 Excel/Word 如何确定哪些类公开,哪些不公开

【问题讨论】:

  • 简单:Excel/Word 甚至不会远程参与。这是 VBE 的工作,而不是宿主应用程序的工作。
  • 那么 VBE 如何知道什么是可访问的,什么是不可访问的?
  • 只有 .NET 类的一个子集是 [ComVisible(true)]。主要是 .NET 1.0 中的东西,那时让程序员跟随 .NET 潮流而不是强迫他们重写他们所拥有的一切仍然很重要。您必须创建自己的 [ComVisible] 包装器。
  • @HansPassant 我把我的答案写成一个有根据的猜测(几年来一直在玩弄 Rubberduck 中的 COM 互操作),如果你能告诉我我的猜测,我会很高兴没错(哎呀,如果你愿意,可以偷那个复选标记)!
  • 没关系,忘记UV了,抱歉。

标签: .net vba excel com


【解决方案1】:

您在调用CreateObject 时指定的参数不是命名空间,而是ProgId - COM 用来定位已注册类(以及它们在其中定义的库和位置)的字符串该库位于),在 Windows 注册表中。

如果没有注册的 COM 类型的 ProgId 值为 System.Management.Automation.Runspaces.RunspaceFactory,则 ActiveX 无法创建该对象。

如果没有用于命名空间的 COM 类型库(即程序集没有为 COM 互操作注册),那么您正试图让 COM 理解 .NET/托管代码,这是它无法做到的。

我不明白的是 Excel/Word 如何确定哪些类是公开的,哪些是不公开的

Excel/Word/任何宿主应用程序都与它无关,它是 VBA 自己的运行时加载 COM 类型,它是包含 ProgId 的 Windows 注册表,用于注册的所有内容。

如果您在HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID 下的注册表中搜索Scripting.Dictionary,您最终会找到一个名为{EE09B103-97E0-11CF-978F-00A02463E06F} 的键,其中ProgID 子键的值为Scripting.DictionaryInprocServer32 子键的值为C:\Windows\system32\scrrun.dll 的值,并且如果 VBA 运行时成功地在该类型库中创建具有指定 ProgId 的类型的实例,则 CreateObject 调用成功并返回该实例。否则,它会抛出错误 429 并显示“ActiveX 无法创建对象”。

【讨论】:

  • FWIW - ProgId 不是 CreateObject 的严格要求 - 可以在其位置使用 CLSID,这在 COM 兼容对象没有 @ 的某些情况下会很有帮助987654337@。一个很好的例子是 MS Forms 2.0 库中的 MSForms.DataObject,它缺少 ProgID: Set objData = CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-07
  • 1970-01-01
相关资源
最近更新 更多