我正在使用VS2010和Windows 7,我的应用程序是SDI共享DLL,从VC6升级。安装我的应用程序后,如果用户双击已注册的文件类型,应用程序将在MFC功能崩溃:
void CRecentFileList::Add(LPCTSTR lpszPathName, LPCTSTR lpszAppID)
{
// ...
#if (WINVER >= 0x0601)
// ...
#ifdef UNICODE
// ...
#endif
ENSURE(SUCCEEDED(hr)); // Crash here: "hr = 0x800401f0 CoInitialize has not been called."
这是从InitInstance()函数调用的:
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
//CString str = cmdInfo.m_strFileName + '\n';
//MessageBox(NULL,str, "MyApp", MB_OK|MB_ICONWARNING);
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
用户选择的文件正确传递(我使用MessageBox检查)。
hr = 0x800401f0似乎是一个COM问题(here),但我没有使用COM或ATL。断言与this相同,但来自不同的原因。德国人和我有同样的问题(here),但我无法理解谷歌翻译(here)!!我不认为这是一个WINVER问题(here)而且我不想解析我自己的东西(like this),只需在用户双击文件时打开应用程序。
感谢您提供的任何帮助:)
答案 0 :(得分:2)
您在代码中添加的注释包含答案:
// Crash here: "hr = 0x800401f0 CoInitialize has not been called."
HRESULT
值告诉您需要调用CoInitialize
function以初始化应用程序线程的COM库。
当然,这个消息有点过时了。正如您在上面链接的文档中所看到的,所有新应用程序都应该调用CoInitializeEx
function。不过不用担心:它与其哥哥基本上是一样的。
正如文件的“备注”部分所示:
对于使用COM库的每个线程,
CoInitializeEx
必须至少调用一次,并且通常只调用一次。 [ 。 。 ]在调用除CoGetMalloc
之外的任何库函数之前,需要在线程上初始化COM库,以获取指向标准分配器的指针以及内存分配函数。否则,COM函数将返回CO_E_NOTINITIALIZED
。
你说你没有使用COM,但这是不正确的。你可能没有明确地使用它,但Windows和MFC框架肯定是在“幕后”使用它。所有文件类型注册函数都依赖于COM。由Visual Studio 2010中的MFC项目向导生成的框架代码将自动插入相应的COM注册代码,但自从VC ++ 6升级现有项目后,您似乎错过了这一重要步骤。
在MFC中,AfxOleInit
function还会为调用应用的当前公寓初始化COM,就像内部OleInitialize
function所做的那样。确保被覆盖的InitInstance
函数包含对其中一个函数的调用。
例如,在VS 2010向导创建的全新MFC项目中,InitInstance
函数看起来像这样:
BOOL CTestApp::InitInstance()
{
// InitCommonControlsEx() is required on Windows XP if an application
// manifest specifies use of ComCtl32.dll version 6 or later to enable
// visual styles. Otherwise, any window creation will fail.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// Set this to include all the common control classes you want to use
// in your application.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
// Initialize OLE libraries
if (!AfxOleInit()) // ** MAKE SURE THAT YOU CALL THIS!! **
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
// . . .
// a bunch more boring initialization stuff...
// The one and only window has been initialized, so show and update it
pFrame->ShowWindow(SW_SHOW);
pFrame->UpdateWindow();
return TRUE;
}