IRunningObjectTable接口

本文介绍了IRunningObjectTable接口的基本概念及其应用。通过详细解释该接口的功能和使用场景,帮助读者更好地理解其在软件开发中的作用。

IRunningObjectTable接口

转载于:https://www.cnblogs.com/time-is-life/p/5765195.html

// MyDialog.cpp: 实现文件 // #include "pch.h" #include "Z3MFCLibrary.h" #include "afxdialogex.h" #include "MyDialog.h" #include "zwapi_file.h" #include "VxApi.h" #include <windows.h> #include <tlhelp32.h> #include <oaidl.h> #include <comdef.h> #include <ocidl.h> // 实现CreateClassEnumerator函数(解决链接错误) HRESULT __stdcall CreateClassEnumerator(REFCLSID clsid, IEnumMoniker** ppenum, DWORD dwFlags) { if (ppenum == nullptr) return E_INVALIDARG; *ppenum = nullptr; // 创建系统类枚举器 IEnumMoniker* pEnum = nullptr; HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, nullptr, CLSCTX_INPROC_SERVER, IID_IEnumMoniker, (void**)&pEnum); if (FAILED(hr)) return hr; // 创建类枚举器 hr = pEnum->EnumClassesOfCategories(1, &clsid, 0, nullptr, ppenum); pEnum->Release(); return hr; } IMPLEMENT_DYNAMIC(MyDialog, CDialogEx) MyDialog::MyDialog(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_DIALOG1, pParent) { } MyDialog::~MyDialog() { } void MyDialog::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_BUTTON1, m_btn_export_import); DDX_Control(pDX, IDC_COMBO1, m_cmbPMWindows); } BEGIN_MESSAGE_MAP(MyDialog, CDialogEx) ON_BN_CLICKED(IDC_BUTTON1, &MyDialog::OnBnClickedExportAndImport) END_MESSAGE_MAP() // 对话框初始化 BOOL MyDialog::OnInitDialog() { CDialogEx::OnInitDialog(); RefreshPMInstances(); // 初始化时加载所有PowerMill实例 return TRUE; } // 枚举PowerMill窗口的回调函数(静态成员函数) BOOL CALLBACK MyDialog::EnumPMWindowsProc(HWND hwnd, LPARAM lParam) { // 获取参数(实例信息向量的指针) std::vector<PMInstanceInfo>* pInstances = reinterpret_cast<std::vector<PMInstanceInfo>*>(lParam); if (!pInstances) return TRUE; // 检查窗口是否可见(使用全局API) if (!::IsWindowVisible(hwnd)) return TRUE; // 获取窗口标题(使用全局API) TCHAR szTitle[256] = { 0 }; ::GetWindowText(hwnd, szTitle, 255); CString title = szTitle; // 筛选标题包含"PowerMill"的窗口 if (title.Find(_T("PowerMill")) == -1) return TRUE; // 获取进程ID(使用全局API) DWORD processId = 0; ::GetWindowThreadProcessId(hwnd, &processId); if (processId == 0) return TRUE; // 添加到实例列表 PMInstanceInfo info; info.index = pInstances->size() + 1; // 序号从1开始 info.processId = processId; info.hwnd = hwnd; info.title = title; pInstances->push_back(info); return TRUE; } // 刷新PowerMill实例列表(显示序号和进程ID) void MyDialog::RefreshPMInstances() { m_pmInstances.clear(); m_cmbPMWindows.ResetContent(); // 枚举所有PowerMill窗口 ::EnumWindows(EnumPMWindowsProc, reinterpret_cast<LPARAM>(&m_pmInstances)); // 添加到组合框(格式:序号 - PID:进程ID - 标题) for (const auto& info : m_pmInstances) { CString itemText; itemText.Format(_T("%d - PID:%d - %s"), info.index, info.processId, info.title.Left(30)); // 限制标题长度 m_cmbPMWindows.AddString(itemText); } // 默认选中第一个实例 if (m_pmInstances.size() > 0) { m_cmbPMWindows.SetCurSel(0); } } // 通过进程ID获取对应的PowerMill COM接口 IDispatch* MyDialog::GetPMInstanceByPID(DWORD pid) { // 初始化COM HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if (FAILED(hr)) return nullptr; // 获取PowerMill的CLSID CLSID clsid; hr = CLSIDFromProgID(L"PowerMILL.Application", &clsid); if (FAILED(hr)) { CoUninitialize(); return nullptr; } // 枚举所有正在运行的PowerMill实例 IEnumMoniker* pEnumMoniker = nullptr; hr = CreateClassEnumerator(clsid, &pEnumMoniker, 0); if (FAILED(hr) || !pEnumMoniker) { CoUninitialize(); return nullptr; } IMoniker* pMoniker = nullptr; IDispatch* pPMApp = nullptr; ULONG fetched = 0; // 遍历所有实例,匹配进程ID while (pEnumMoniker->Next(1, &pMoniker, &fetched) == S_OK) { // 获取实例的进程ID DWORD instancePid = 0; IBindCtx* pBindCtx = nullptr; if (CreateBindCtx(0, &pBindCtx) == S_OK) { ULONG len = 0; LPOLESTR displayName = nullptr; if (pMoniker->GetDisplayName(pBindCtx, nullptr, &displayName) == S_OK) { // 从显示名称中提取进程ID(格式类似"PowerMILL.Application.19:1234") CString displayStr(displayName); int colonPos = displayStr.ReverseFind(':'); if (colonPos != -1) { CString pidStr = displayStr.Mid(colonPos + 1); instancePid = _ttoi(pidStr); } SysFreeString(displayName); } pBindCtx->Release(); } // 匹配目标进程ID if (instancePid == pid) { // 获取该实例的COM接口 hr = pMoniker->BindToObject(nullptr, nullptr, IID_IDispatch, (void**)&pPMApp); if (SUCCEEDED(hr)) { pMoniker->Release(); break; } } pMoniker->Release(); } pEnumMoniker->Release(); CoUninitialize(); return pPMApp; } // 导出X_T文件 bool MyDialog::ExportXtFile(CString& filePath) { filePath = _T("C:\\Users\\Administrator\\Desktop\\Test.x_t"); svxPARAData exportData; evxErrors result = cvxFileExportInit(VX_EXPORT_TYPE_PARA_TEXT, 0, &exportData); if (result != ZW_API_NO_ERROR) { AfxMessageBox(_T("初始化导出参数失败!"), MB_OK | MB_ICONERROR); return false; } exportData.Coordinate = 0; exportData.OutPut = 1; exportData.FileVer = 19; exportData.WriteFreeCrv = TRUE; exportData.WriteFreePnt = FALSE; exportData.HealErr = FALSE; exportData.ExportType = 0; exportData.ExcludeGeom = VX_EXCLUDE_BLANKED; result = cvxFileExport(VX_EXPORT_TYPE_PARA_TEXT, (LPCSTR)CStringA(filePath), &exportData); if (result != ZW_API_NO_ERROR) { CString errMsg; errMsg.Format(_T("X_T文件导出失败!错误代码: %d"), result); AfxMessageBox(errMsg, MB_OK | MB_ICONERROR); return false; } return true; } // 导入到选定的PowerMill实例 bool MyDialog::ImportToPowerMill(const CString& filePath) { // 检查文件是否存在 if (_taccess(filePath, 0) == -1) { AfxMessageBox(_T("X_T文件不存在!"), MB_OK | MB_ICONERROR); return false; } // 检查是否有选中的实例 int selectedIndex = m_cmbPMWindows.GetCurSel(); if (selectedIndex == CB_ERR || m_pmInstances.empty()) { AfxMessageBox(_T("请先选择一个运行中的PowerMill实例!"), MB_OK | MB_ICONERROR); return false; } // 获取选中实例的进程ID DWORD targetPid = m_pmInstances[selectedIndex].processId; // 获取对应实例的COM接口 IDispatch* pPMApp = GetPMInstanceByPID(targetPid); if (!pPMApp) { AfxMessageBox(_T("无法连接到选中的PowerMill实例!"), MB_OK | MB_ICONERROR); return false; } // 执行导入命令 bool success = false; try { // 构造命令 CString command; command.Format(_T("FORM RIBBON BACKSTAGE CLOSE IMPORT MODEL FILEOPEN \"%s\""), filePath); // 获取命令执行方法ID(尝试常见方法名) DISPID dispid; LPOLESTR methodNames[] = { L"DoCommand", L"ExecuteCommand", L"RunCommand" }; HRESULT hr = E_FAIL; for (auto methodName : methodNames) { hr = pPMApp->GetIDsOfNames(IID_NULL, &methodName, 1, LOCALE_SYSTEM_DEFAULT, &dispid); if (SUCCEEDED(hr)) break; } if (FAILED(hr)) { throw _T("未找到可用的命令执行方法(DoCommand/ExecuteCommand/RunCommand)"); } // 准备参数 VARIANT varArg; VariantInit(&varArg); varArg.vt = VT_BSTR; varArg.bstrVal = SysAllocString(command); DISPPARAMS dispParams = { &varArg, NULL, 1, 0 }; VARIANT result; VariantInit(&result); // 执行命令 hr = pPMApp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispParams, &result, NULL, NULL); if (FAILED(hr)) { throw _T("命令执行失败,可能是命令格式错误"); } success = true; VariantClear(&varArg); VariantClear(&result); } catch (LPCTSTR errMsg) { CString msg; msg.Format(_T("导入失败:%s\n实例PID: %d"), errMsg, targetPid); AfxMessageBox(msg, MB_OK | MB_ICONERROR); } // 释放资源 if (pPMApp) { pPMApp->Release(); } return success; } // 按钮点击事件 void MyDialog::OnBnClickedExportAndImport() { // 刷新实例列表(确保最新) RefreshPMInstances(); // 检查是否有PowerMill实例在运行 if (m_pmInstances.empty()) { AfxMessageBox(_T("未检测到运行中的PowerMill实例!"), MB_OK | MB_ICONERROR); return; } // 导出X_T文件 CString xtFilePath; if (!ExportXtFile(xtFilePath)) { return; } // 导入到选定的PowerMill实例 if (ImportToPowerMill(xtFilePath)) { CString msg; msg.Format(_T("操作完成!\n已导入到PowerMill实例(PID: %d)"), m_pmInstances[m_cmbPMWindows.GetCurSel()].processId); AfxMessageBox(msg, MB_OK | MB_ICONINFORMATION); } } 严重性 代码 说明 项目 文件 行 抑制状态 详细信息 错误 C2039 "EnumClassesOfCategories": 不是 "IEnumMoniker" 的成员 Z3MFCLibrary C:\Users\Administrator\Desktop\Z3MFCLibrary\MyDialog.cpp 32 错误 C2065 “CLSID_SystemDeviceEnum”: 未声明的标识符 Z3MFCLibrary C:\Users\Administrator\Desktop\Z3MFCLibrary\MyDialog.cpp 26 错误(活动) E0020 未定义标识符 "CLSID_SystemDeviceEnum" Z3MFCLibrary C:\Users\Administrator\Desktop\Z3MFCLibrary\MyDialog.cpp 26 错误(活动) E0135 类 "IEnumMoniker" 没有成员 "EnumClassesOfCategories" Z3MFCLibrary C:\Users\Administrator\Desktop\Z3MFCLibrary\MyDialog.cpp 32
最新发布
08-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值