【问题标题】:Debug a MS Word Macro Invoked from another app using OLE使用 OLE 调试从另一个应用程序调用的 MS Word 宏
【发布时间】:2014-05-12 20:39:34
【问题描述】:

我有一个 C++ 应用程序,它在 .docm 文件中的 word 宏中调用邮件合并。该宏适用于 Windows XP,但不适用于 Windows 7。我想首先在它工作的 Windows XP 中调试该宏,然后移至它不工作的 Windows 7。

我在宏中设置了一个断点以进行调试,但是当从我的应用程序调用时,我无法让调试器参与其中。很多年前我曾经这样做过(以及 WORD 的版本)。是否仍然可以这样做,我在最后一天半的时间里用谷歌搜索了这个,但我什么也没想到。

【问题讨论】:

  • 还有相关的:什么版本的 Word?
  • 感谢您花时间阅读和考虑我的帖子。在我的 XP 和 Win 7 机器上使用的 Word 版本都是 2010。在我在 2010 年运行它之后,我将适应 Word 2013。C++ 应用程序的 IDE 是 Visual Studio 6。尽管 VS 6 C++ IDE 无法在 Win 7 上安装,但 C++ 可执行文件在 Win 7 中运行没有问题。更多细节;我已经进入 Word 的信任中心设置并设置了“启用所有宏”单选按钮,这是完成这项工作的必要步骤。我还设置了“信任对 VBA 项目对象模型的访问”,但没有成功。
  • 在 Win 7 中录制宏并保存后,我不得不重新打开它并将其转换为 2010,就好像它来自 Word 的早期版本一样,以阻止它以兼容模式出现,据我了解,禁用宏。
  • 总之,此宏在 XP 机器上的 Word 2010 中(通过 C++ 应用程序中的 OLE 调用)有效,但在 Win 7 计算机上无效。我想在宏启动时自动使用 VBA 宏调试器,首先是在 XP 环境中运行,然后在 Win 7 环境中找出问题所在。我已经确认我已经在 C++ 应用程序调用的同一宏实例中设置了断点,并且我无法让 VBA 宏调试器从任一操作系统中使用。

标签: vba debugging ole


【解决方案1】:

如果您的 c++ 应用程序使用 CoCreateInstance 将 Word 作为本地服务器加载,那么您在 Word VBA IDE 宏中设置的断点将不会被触发,因为 CoCreateInstance 正在为 Word 启动一个新进程。

仅打开 word 实例,在宏中设置断点,然后在 c++ 应用程序中使用 GetActiveObject(而不是 CoCreateInstance)来获取对 Word 本地服务器的引用。这应该会触发你的断点。

例如,我创建了一个名为 TestMacro 的 Word 宏,它只显示了一个消息框。我在宏中的 MsgBox "..." 上设置了一个断点。然后我从 .vbs 脚本中调用了我的宏:

dim wdApp
set wdApp = GetObject(, "Word.Application")
'set wdApp = CreateObject("Word.Application")

wdApp.Run "TestMacro"

当我使用 GetObject 时,我的断点被触发。当我使用 CreateObject 时,我的断点没有触发。

【讨论】:

  • 我调用 Word 的应用程序是用 C++ 而不是 VBS 编写的。我真的不知道它是否等同于上面的 VBS。这个评论字段更长,所以我将把它分成两部分。这是第一部分:
  • WordApplication glWordAppVer8Obj; WordBasic glWordBasicObj; ::CLSIDFromProgID(L"Word.Application", &clsid); glWordAppVer8Obj.ReleaseDispatch(); glWordBasicObj.ReleaseDispatch(); glWordAppVer8Obj.CreateDispatch("Word.Application", &glWordOLEException) glWordBasicObj.AttachDispatch(glWordAppVer8Obj.GetWordBasic()); glWordAppVer8Obj.SetVisible(TRUE); glWordAppVer8Obj.SetWindowState(2);
  • glWordBasicObj.FileNew(COleVariant(LPCTSTR( "I:\TemplateDiy\REPORT.docm")), COleVariant((short) 0)); glWordBasicObj.ViewNormal(); glWordBasicObj.SetDocumentVar("LetterFile", "I:\TemplateDir\LetterTemplate.docx"); glWordBasicObj.SetDocumentVar("TempFileName", "C:\TempDir\MyMergeData.txt"); glWordBasicObj.ToolsMacro(COleVariant("MyMacroName"), COleVariant((short) TRUE), COleVariant((short) FALSE), COleVariant((short) 3), COleVariant((short) FALSE), COleVariant((short) FALSE) , COleVariant(""), COleVariant(""), COleVariant((short) FALSE));
  • 如果CreateDispatch内部调用CoCreateInstance,我想你可以修改你的c++代码调用GetActiveObject。而不是调用glWordAppVer8Obj.CreateDispatch("Word.Application", &glWordOLEException) 调用IUnknown * pUnk; IDispatch * pdispWdApp; HRESULT hr = GetActiveObject(clsid, NULL, &pUnk); hr = pUnk->QueryInterface(IID_IDispatch, &pdispWdApp); glWordAppVer8Obj.AttachDispatch(pdispWdApp);
  • 通话时 hr = pUnk->QueryInterface(IID_IDispatch, &pdispWdApp);我收到一个编译错误; “错误 C2664:‘long __stdcall IUnknown::QueryInterface(const struct _GUID &,void **)’:无法将参数 2 从‘struct IDispatch **’转换为‘void **’指向的类型不相关;转换需要 reinterpret_cast, C 样式转换或函数样式转换”。 C 样式转换 (void**) 编译但失败。我不经常涉足 COM,如果您对这次调用 QueryInterface 有任何建议,我将不胜感激。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多