如何在VS2012 MFC项目中加载类实现软件自动化
在Visual Studio 2012的MFC项目中实现目标应用程序自动化
最近我在VS2012的MFC应用里做软件自动化,已经通过类型库向导加载了目标应用的类(比如生成的CGPNSApplicationDisp),现在有一段初步的代码,我把它完善了下,分享给大家参考:
现有初始代码片段
#include "stdafx.h" #include "MFCApplication1.h" #include "CGPNSApplicationDisp.h" #include "ChildFrm.h" #include <iostream> #include <string> void CChildFrame::AssertValid() const { CLSID clsid; LPDISPATCH pWMPDispatch = NULL; ::CLSIDFromProgID(OLESTR(...
完整实现方案
步骤拆解与代码完善
要让这段代码真正实现自动化,需要补全COM操作的关键环节,下面是完善后的代码,我会标注关键细节:
#include "stdafx.h" #include "MFCApplication1.h" #include "CGPNSApplicationDisp.h" #include "ChildFrm.h" #include <iostream> #include <string> #include <atlbase.h> // 引入ATL头文件,简化COM操作 void CChildFrame::AssertValid() const { // 去掉const限制,方便后续操作 CChildFrame* pThis = const_cast<CChildFrame*>(this); HRESULT hr; // 初始化COM库,MFC单线程公寓(STA)模式下,也可以在App的InitInstance里统一初始化 hr = CoInitialize(NULL); if (FAILED(hr)) { AfxMessageBox(_T("COM组件初始化失败!")); return; } CLSID clsid; // 替换成你的目标应用的ProgID,比如"GPNS.Application",要和类型库对应 hr = CLSIDFromProgID(OLESTR("GPNS.Application"), &clsid); if (FAILED(hr)) { AfxMessageBox(_T("获取目标应用CLSID失败,请检查ProgID是否正确!")); CoUninitialize(); return; } LPDISPATCH pDispatch = NULL; // 优先尝试连接到已经运行的应用实例,没有再创建新实例 hr = GetActiveObject(clsid, NULL, (IUnknown**)&pDispatch); if (FAILED(hr)) { // 尝试创建新的应用实例 hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&pDispatch); } if (SUCCEEDED(hr) && pDispatch) { // 用向导生成的CGPNSApplicationDisp类包装Dispatch指针 CGPNSApplicationDisp appObj; appObj.AttachDispatch(pDispatch); // 这里就可以调用目标应用提供的方法和属性了 // 举个例子:如果目标应用有打开文档的方法 // appObj.OpenDocument(_T("D:\\test_file.gpns")); // 或者获取应用版本信息 // CString version = appObj.GetVersion(); // 使用完记得释放Dispatch指针,避免内存泄漏 appObj.ReleaseDispatch(); } else { AfxMessageBox(_T("无法创建或连接到目标应用程序!")); } // 释放COM库资源 CoUninitialize(); // 别忘了调用基类的AssertValid方法 CChildFrame::AssertValid(); }
必须注意的几个点
- COM初始化:如果你的MFC项目是多线程,要使用
CoInitializeEx指定合适的线程模型;单线程的话,也可以在CWinApp::InitInstance里调用AfxOleInit()来代替CoInitialize,更符合MFC的习惯。 - ProgID准确性:ProgID必须和目标应用的注册表信息一致,你可以打开注册表编辑器,在
HKEY_CLASSES_ROOT下查找对应的应用名称,确认ProgID。 - 错误处理:每个COM操作的返回值
HRESULT都要检查,不然很容易出现崩溃或未知错误。 - 资源释放:
AttachDispatch后一定要调用ReleaseDispatch,或者手动调用pDispatch->Release(),确保COM对象被正确释放。
内容的提问来源于stack exchange,提问作者mahdi Lotfi




