【问题标题】:Debugging COM server connection to VBA / Excel调试 COM 服务器与 VBA / Excel 的连接
【发布时间】:2015-01-30 05:49:46
【问题描述】:

我遵循了为 Python comtypes 模块 (http://pythonhosted.org/comtypes/server.html) 提供的文档并构建了一个简单的 COM 服务器。

它似乎工作正常。我可以看到类型库和接口已注册(使用 Oleviewer),并且我可以从 Python 脚本调用添加两个整数的(单个)方法。

但是,我无法使其与 Excel(Office 2007,在 Win7 上运行)一起使用。以下简单函数不起作用(调用 MyMethod 时执行停止)

Function test(a, b)
    Dim x As New MyTypeLib.MyObject
    ab = x.MyMethod(a, b)
    Debug.Print "d" & CStr(ab)
    test = ab
End Function

有什么办法可以调试吗?

更多cmets

隧道尽头确实有光。使用 VBScript 的建议很有帮助。以下简短脚本确实有效(提供 COM 服务器工作的独立确认)。

Dim x,ab
Set x = CreateObject("MyTypeLib.MyObject")
ab = x.MyMethod(1, 2)
MsgBox CStr(ab)

但是,VBScript 正在使用后期绑定调用服务器,我试图让早期绑定工作。

所以,我更改了我的 Excel VBA 函数以使用后期绑定和预期的事情,但他们没有。

这是修改后的 VBA:

Function test(a, b)
    Dim x As Object
    Set x = CreateObject("MyTypeLib.MyObject")
    gadd = x.MyMethod(1, 5)
End Function

所以我的服务器可以用于 Python 和 VBScript 的后期绑定,但不能用于 Excel!

使用进程监视器我可以看到,在后期和早期绑定情况下,Excel 都无法成功加载 msvcr90.dll,即使系统上安装了此 DLL。

这是来自 Process Monitor 的屏幕截图,显示 64 位 Windows 7 Home Edition 上的 Office Excel 2007 开始尝试加载 msvcr90.dll

【问题讨论】:

  • 它可以在独立的VBScript 上工作吗? (见MSDN: VBSCript > CreateObject
  • 我不知道。我没有 VBScript(那不需要 ASP 服务器吗?)
  • 很抱歉,提出一个明确的问题是一项挑战。我在完全不同的位置有两台机器。识别我正在处理的两台机器可能会有所帮助。两者都运行 64 位 Win7,但一个(称为“A”)使用“家庭”版本,另一个(称为“B”)运行 Win7 专业版。在机器 A 上我有 Office 2007 和在 B 上 Office 2013。我安装了完全相同的 Python 版本来在每台机器上创建 COM 服务器,并且所有项目文件都通过云驱动器同步。
  • 在机器 B 上,事情开始工作,但后来我在 A 上发现问题仍然存在。我一直在检查注册表项是否引用了最新的类型库。我认为没关系。在机器 A 上使用进程监视器,我可以看到 msvcr90.dll 没有找到(从 PATH 中搜索了一整套不同的文件夹,然后 Excel 悄悄地放弃了)。 DLL 已安装在机器上(我确定运行了 vcredist_x86.exe)。再次使用进程监视器,但使用 VBScript,msvcr90.dll 没有使用。
  • 我已经尝试过制作和注册本地服务器。看起来很有希望(但我必须等待在机器 A 上尝试)。有一个解决方案会很好,但与进程内服务器相比,我担心这会增加每个方法调用的开销(并且我的预期应用程序将对性能开销敏感)。我记得看到(在这个传奇的某个时刻)mscvr89.dll 和 mscvr90.dll 加载并并排工作。所以,我想尝试解决这个问题,而不仅仅是避免它。

标签: python vba excel com


【解决方案1】:

当我发布这个问题时,我需要了解更多关于如何调试 COM 服务器的信息(实际上要了解更多!)。事实证明,有几个问题使我的服务器无法工作。我认为了解这些工具可能与实际问题一样令人感兴趣,因此此答案将尝试涵盖两者。

最初,使用 VBScript 提供对服务器已注册和工作的独立验证很有帮助(上面显示了简单的代码)。 VBScript 使用后期绑定,我想要早期绑定,但它仍然很有帮助,因为我随后意识到 Excel 也不能使用后期绑定 VBA 代码(在机器 A 上)!

VBScript 也发生了一些奇怪的事情。当我第一次编写脚本时,它们默认运行(单击 Windows 资源管理器中的文件),但随后无缘无故停止工作。我发现我需要指定 32 位版本的完整路径 (C:\WINDOWS\SysWOW64\cscript.exe) 才能让它们工作。

另外值得注意的是,通过使用cscript.exe 而不是wscript.exe,嵌入在我的 Python 模块中的调试消息会出现在 Windows CMD 窗口中。

下一个突破来自于使用 Dependency Walker 程序 depends.exe。这在像我这样的帖子中经常提到,人们试图找出 DLL 不工作的原因。

Dependency Walker 可从其自己的网站获得,但该版本无法在 Windows 7 上正常工作(请参阅 Profiling x86 executable with Dependency Walker hangs on Windows 7 x64),因此我发现我需要安装 WDK 8.1(来自此处:http://msdn.microsoft.com/en-US/windows/hardware/gg454513)。

DW 非常强大,一开始有点压倒性。但是,通过读取其日志输出,可以清楚地看出 Excel 2007 使用 msvcr80.dll 并且服务器尝试加载 msvcr90.dll 失败(即使 DLL 已正确安装在计算机上)。这在机器 B 上不是问题,因为 Excel 2013 使用 msvcr90.dll。

现在,在这些测试中,我以交互方式使用 Python comtypes 创建服务器(不涉及服务器 DLL)。但也有可能使用py2exe 工具创建一个DLL。我也在尝试这样做,DLL 无法使用 regsvr32 注册。

DW 也帮助调试了这个问题。令人高兴的是,在日志输出中,我注意到 Python 异常的堆栈跟踪。它是示例中的GetModule()。事实证明,这个调用只需要一次,以创建一些 Python 类,然后缓存在机器上。删除此命令解决了问题。

另外,虽然可能没有造成问题,py2exe 的官方当前版本是 0.6.9 但这导致了一些不再可用的文件被捆绑(特别是zlib.pyd)。非官方版本 0.6.10(可在此处获取:http://www.lfd.uci.edu/~gohlke/pythonlibs/#py2exe)解决了该问题。

所以我现在可以编译一个 COM 服务器 DLL,我可以在其中包含所需的 msvcr90.dll,而且,是的,它可以在两台机器上运行 :-)

总结一下。混合了 32 位和 64 位库的 Windows 7 是一场噩梦。 VBScript 通过为测试服务器提供独立的环境来提供帮助。 Dependency Walker 确实很棒,但需要很长时间才能学会使用(WDK 中的其他有用工具包括 oleviewerprocess-monitorprocess-explorer)。

【讨论】:

    猜你喜欢
    • 2017-09-09
    • 1970-01-01
    • 1970-01-01
    • 2011-11-10
    • 1970-01-01
    • 2013-06-10
    • 2015-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多