我如何知道我的 MFC 应用程序是不是使用 COM / OLE?
Posted
技术标签:
【中文标题】我如何知道我的 MFC 应用程序是不是使用 COM / OLE?【英文标题】:How do I know if my MFC Application use COM / OLE?我如何知道我的 MFC 应用程序是否使用 COM / OLE? 【发布时间】:2020-10-15 09:09:51 【问题描述】:我从 Win7 到 Win10,最近打开文件时遇到“不正确的参数错误”。
该错误非常罕见且随机发生。
没有提供进一步的信息或调用堆栈信息。我曾在 MFC 代码中进行过深入搜索。 DocManager 打开文档,然后调用CDocument::SetPathName(..,TRUE)
将当前文件也添加到最近文件列表中。
这个函数现在似乎使用了一个 OLE/COM 函数。
void CRecentFileList::Add(LPCTSTR lpszPathName, LPCTSTR lpszAppID)
:
:
Add(lpszPathName);
HRESULT hr = S_OK;
CComPtr<IShellItem> psi = NULL;
hr = _AfxSHCreateItemFromParsingName(lpszPathName, NULL, IID_IShellItem, reinterpret_cast<void**>(&psi));
ENSURE(SUCCEEDED(hr)); // Remark Tom: This throws an AfxInvalidException()
hr ErrorCode 为 -2147221008,表示CoInitialize
未被调用。
我很惊讶,因为我从未使用过 COM / OLE 的东西。
一定要克服这个错误,我必须在InitInstance
中添加AfxOleInit()
。
我的问题是,我如何提前知道我的应用程序是否需要使用 OLE / COM?
附加问题,如果我在我的应用程序中使用 COM / OLE,我有什么缺点吗? (内存和速度)?
【问题讨论】:
由于通过 COM 公开了如此多的 Windows API 表面,因此可以合理猜测任何重要的 Windows 应用程序都会在某个时候使用 COM。将线程初始化为 COM 单元不是免费的。一旦完成,就没有任何运行时开销。为 COM 注册线程不太可能表现出任何可观察到的性能下降。请注意,COM 是按线程初始化的。InitInstance
中的单个初始化调用只会注册您的 UI 线程。
P.S.:您的 MFC 应用程序可能一直使用 COM,但即使它应该使用它也没有失败(有关详细信息,请参阅 Why does CoCreateInstance work even though my thread never called CoInitialize? The curse of the implicit MTA)。也许在 Windows 10 中发生了一些变化。
【参考方案1】:
我的问题是,我如何提前知道我的应用程序是否需要使用 OLE / COM?
MFC 应用程序应该始终初始化 OLE/COM,特别是使用 STA(单线程单元)的并发模型。这是在向导生成的模板中自动完成的,否则必须在用户代码中明确完成。来自CWinApp 文档:
MFC 应用程序必须初始化为单线程单元 (STA)。
如果您在 InitInstance 覆盖中调用 CoInitializeEx,请指定 COINIT_APARTMENTTHREADED(而不是 COINIT_MULTITHREADED)。
始终将 OLE/COM 初始化为 STA 还可以避免 @IInspectable 在评论中提到的 the curse of the implicit MTA。
【讨论】:
以上是关于我如何知道我的 MFC 应用程序是不是使用 COM / OLE?的主要内容,如果未能解决你的问题,请参考以下文章