在CRecentFileList ::添加命令行FileOpen上MFC应用程序断言失败

时间:2011-07-09 07:56:36

标签: c++ visual-studio visual-studio-2010 com mfc

我正在使用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),只需在用户双击文件时打开应用程序。

感谢您提供的任何帮助:)

1 个答案:

答案 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;
}