我已经创建了一个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,它就可以运行!!!。
请帮助我理解。
答案 0 :(得分:1)
{ CCostTestFactory costFactory; HRESULT hr = CoRegisterClassObject(CLSID_CostTest, (IClassFactory*)&costFactory, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &m_RegID); }
为COM运行时提供指向局部变量的指针。不久之后,该变量超出范围并被销毁,使系统留下悬空指针。然后系统通过悬空指针调用一个方法,然后繁荣。