Click here to Skip to main content
15,904,346 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi,

I am writing an out-of-process COM server (*.exe) which should display a dialog using a resource template. The resource is contained in the server's exe file. I am using VC++ 2010, and the project has MFC support and makes heavy use of MFC classes. The code boils down to this:
STDMETHODIMP CMyComServer::MyMethod()
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState())
    AfxSetResourceHandle(_AtlBaseModule.GetResourceInstance()); // see text below
    CWinApp *pApp = AfxGetApp(); // see text below

    CDialog objDlg(IDD_MY_DIALOG, NULL);
    objDlg.DoModal();
    return S_OK;
}


What happens is this: The call to DoModal asserts when CWnd::CreateDlgIndirect calls AfxGetApp()->IsKindOf(RUNTIME_CLASS(COleControlModule)) because AfxGetApp() returns a NULL pointer.

To verify this, I inserted the line CWinApp *pApp = AfxGetApp(); which assigns NULL to pApp.

When I remove the call to AfxSetResourceHandle, the assertion is triggered in AfxGetResourceHandle() because afxCurrentResourceHandle is NULL.

My project seems not to have a CWinApp-derived class. VC++ 2010 does not provide a COM out-proc server wizard, so I cloned an out-proc server project which has no GUI. Do I have to add an application object? If so, how?

Thanks... Hans
Posted
Comments
BadJerry 18-Jun-13 9:06am    
Did you find a solution to this? I have the same problem!

BadJerry, I found a solution that worked for me. However after such a long time I am not at all sure what the key points were. I hope these chunks of code can help you. I removed all error checking.

This function implements the COM interface. It creates a MFC GUI thread which displays the dialog.

C++
STDMETHODIMP CMyComServer::MyInterfaceFunction(...)
{
    // Don't call AFX_MANAGE_STATE!
    AfxSetResourceHandle(_AtlBaseModule.GetResourceInstance());
    CMyGuiThread *pThread = dynamic_cast<cmyguithread*>AfxBeginThread(RUNTIME_CLASS(CMyGuiThread)));
}


The GUI thread, in its InitInstance function, creates the dialog.

C++
/*virtual*/ BOOL CMyGuiThread::InitInstance()
{
    CMyDlg *pWnd = new CMyDlg;
    BOOL bRes = pWnd->Create();
    if (bRes)
        m_pWnd = pWnd;
    else
        delete pWnd;
    return bRes;
}


The CMyGuiThread::m_pWnd member stores a pointer to the CMyDlg object so that you can destroy the dialog when it is no longer required. (Be aware that a dialog can destroy itself in response to IDOK or IDCANCEL control clicks and inresponse to a click on the X icon in the upper right corner; in that case, m_pWnd points to invalid memory; you must overwrite CMyDlg::OnCancel and OnOk to prevent this.)

The dialog, in its Create function, calls one of the inherited overloads.

C++
/*virtual*/ BOOL CMyDlg::Create()
{
    return __super::Create(IDD, NULL);
}


Maybe the important thing is not to use the AFX_MANAGE_STATE macro which you usually put at the beginning of each method that is called over the COM interface.
 
Share this answer
 
v2
Comments
acolada 20-Nov-14 17:24pm    
this worked for me too:
AfxSetResourceHandle(_AtlBaseModule.GetResourceInstance());
instead of AFX_MANAGE_STATE(...)
you've already used ATL to create the Server, so use WTL to do the dialog, throw MFC away :)

Look at CDialogImpl<>[^]
 
Share this answer
 
Comments
hans.sch 20-May-11 5:20am    
I get your point. However junking MFC is no option. I have to follow company guidelines, and besides, our code base makes heavy use of MFC. No, I must do with CDialog, CWinApp, etc.
barneyman 20-May-11 6:01am    
Sorry - I can't help you then

I've retrofitted an ATL server into an MFC app, but not the other way around ...

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900