作为MFC模式对话框实现的COM Out of Process Server(CLSCTX_LOCAL_SERVER)失败

时间:2014-02-01 08:41:37

标签: com

我已经创建了一个COM进程服务器。此服务器是默认模式对话框,带有两个按钮“确定”和“取消”。

这是我在CCostTestApp :: InitInstance()

中注册进程外COM服务器的方法
BOOL CCostTestApp::InitInstance()
{
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();

AfxEnableControlContainer();

// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need
// Change the registry key under which our settings are stored
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization
SetRegistryKey(_T("Local AppWizard-Generated Applications"));

//**Registering Out-of Process COM Server**
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);     

CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);

// Let's see if we were started by SCM.
//if(strstr(lpCmdLine, "/Embedding") || strstr(lpCmdLine, "-Embedding"))
if(cmdInfo.m_bRunEmbedded == TRUE)
{
    CCostTestFactory costFactory;

    HRESULT hr = CoRegisterClassObject(CLSID_CostTest, (IClassFactory*)&costFactory, 
        CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &m_RegID);
    if ( FAILED(hr) )
    {
        CoUninitialize();
        return FALSE;
    }
}


CCostTestDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
    // TODO: Place code here to handle when the dialog is
    //  dismissed with OK
}
else if (nResponse == IDCANCEL)
{
    // TODO: Place code here to handle when the dialog is
    //  dismissed with Cancel
}

// Since the dialog has been closed, return FALSE so that we exit the
//  application, rather than start the application's message pump.

return FALSE;

}

我正在为这个COM服务器创建一个客户端作为控制台exe,我将从中查询该接口。

CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

IUnknown* pIUnknow = NULL;
HRESULT hr = CoCreateInstance(CLSID_CostTest, NULL , CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&pIUnknow);
if (NULL == pIUnknow)
{   
    cout<< "NULL Interface";
}
CoUninitialize();
return 0;

现在,CoCreateInstance失败,错误“Server Execution Failed。”

我Debuged,服务器代码,发现服务器被正确注册,因为CoRegisterClassObject()返回S_OK,我得到了类对象。

然而,在此之后,当它尝试创建对话框时,使用DoModal(),它将消息泵入循环,第一条带有“49214”的消息成功后,它尝试使用id“1024”。这会引发异常“CostTest.exe中0xffffffff处的未处理异常:0xC0000005:访问冲突。”

我第一次实现COM服务器时完全迷失了。

另外,如果我将COM服务器创建为一个简单的控制台exe,它就可以运行!!!。

请帮助我理解。

1 个答案:

答案 0 :(得分:1)

{
    CCostTestFactory costFactory;

    HRESULT hr = CoRegisterClassObject(CLSID_CostTest, (IClassFactory*)&costFactory, 
        CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &m_RegID);
}

为COM运行时提供指向局部变量的指针。不久之后,该变量超出范围并被销毁,使系统留下悬空指针。然后系统通过悬空指针调用一个方法,然后繁荣