Link to home
Start Free TrialLog in
Avatar of marisademeglio
marisademeglio

asked on

MFC DLL

Hi,

I need to create a dialog in an MFC DLL.  It will be a plugin for my main application.  Here are the basics of what I have set up:

1. client = MFC  MDI app (running in Debug mode)
2. DLL = appwizard MFC extension DLL (running in debug mode)
Uses MFC libraries as a shared DLL

Has the following structure:
 - CPluginDialog: CDialog-derived class
 - something.cpp: wizard-generated DLL entry point
 - IPlugin: exported interface for starting/stopping the plugin which looks like this:

class AFX_EXT_CLASS IPlugin
{
...
void Start()
{
      CPluginDialog dlg;
      dlg.DoModal();
}
};

I am getting a debug assertion upon dlg.DoModal.  Also, adding the line AFX_MANAGE_STATE(AfxGetStaticModuleState(...) doesn't help.  I tried adding it in a few places.  It gets linker errors.

Any ideas?

thanks!
marisa
ASKER CERTIFIED SOLUTION
Avatar of AlexFM
AlexFM

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of nonubik
nonubik

>It gets linker errors.
What linker errors? It should work ok.

void Start()
{
     AFX_MANAGE_STATE(AfxGetStaticModuleState());
     CPluginDialog dlg;
     dlg.DoModal();
}
Avatar of AndyAinscow
Try putting a breakpoint on the line
 dlg.DoModal();
Now step into the code.  Where does it assert?


If you have an OnInitDialog in the CPluginDialog class then try a breakpoint there also.
Avatar of marisademeglio

ASKER

1. The linker errors are:

mfcs42d.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in pluginA.obj
mfcs42d.lib(dllmodul.obj) : error LNK2005: __pRawDllMain already defined in pluginA.obj

when I add AFX_MANAGE_STATE(AfxGetStaticModuleState()); at the beginning of my Start() function.

2. I put a breakpoint in MyDialog::DoModal() and it crashes as it calls CDialog::DoModal.

The hWnd of MyDialog is NULL, which is probably what is causing the problem.  But I don't know how to fix it...

Thanks
marisa
Further info...

the assertion is happening here:
afxwin1.inl
line 22
Did you read my post?
Thanks Alex, I had missed it.

When I tried your suggestion, I get the same assertion as before, but at this line:

       HINSTANCE h = AfxGetResourceHandle();
What assertion? Can you post assertion line (number and the whole function where assertion is raised)?
There are two types of MFC Dll. In one of them AFX_MANAGE_STATE is working. Another Dll type doesn't like AFX_MANAGE_STATE. I am always working with MFC extension Dll and use  AfxGetResourceHandle/AfxSetResourceHandle to manage Dll resources. Possibly your problem is the same.
Assertion:
afxwin1.inl
line 22

And the function is:

void InterfaceForPluginA::Start()
{
      CPluginDialog dlg;

       HINSTANCE h = AfxGetResourceHandle();
      AfxSetResourceHandle(g_hDll);   // get hDll from HINSTANCE passed to DllMain
      dlg.DoModal();
      AfxSetResourceHandle(h);
}
Yeah, this is an extension DLL.  It didn't like AFX_MANAGE_STATE.
Interesting. Current resource handler is NULL. Is this standard MFC Dll created by MFC Wizard statically linked to client MFC application? Or there is something custom in the way you use it? Try to continue ignoring assertion, what result do you have?
This DLL is a standard MFC extension DLL, using MFC as a shared DLL.

It is statically linked to the client application (for now but in the end it will be loaded dynamically).

Assertion:
afxwin1.inl
line 19

In function:
int CPluginDialog::DoModal()
{
      return CDialog::DoModal();
}

I ignore it twice then get an access violation before the calling function returns.  I think it is trying to show the plugin window since I see a new window item on my taskbar menu named "plugin" (which would be the correct output of this test) right before it crashes.


to clarify...

First I get this assertion:
 Assertion: afxwin1.inl, line 22
In the IPlugin::Start() function.

Then I get (twice):
Assertion: afxwin1.inl, line 19
In CPluginDialog::DoModal()

Then it crashes with an access violation, I think as it tries to InitDialog().
Something is completely wrong in your Dll or in the way it is invoked, if both AfxGetInstanceHandle and AfxGetResourceHandle fail.
Please post here file where DllMain function is placed.
The file is almost 100% MFC wizard generated except for where I save the HINSTANCE of DLLMain.
Tomorrow I should be able to post the project files on our website and also include a sample test client app to reproduce the error.
Thanks for your help
marisa

--start file---
// pluginA.cpp : Defines the initialization routines for the DLL.
//

#include "stdafx.h"
#include <afxdllx.h>

//added this line to wizard generated file
#include "global.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


static AFX_EXTENSION_MODULE PluginADLL = { NULL, NULL };

//global variable
HINSTANCE g_hDll;

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
      // Remove this if you use lpReserved
      UNREFERENCED_PARAMETER(lpReserved);

      if (dwReason == DLL_PROCESS_ATTACH)
      {
            TRACE0("PLUGINA.DLL Initializing!\n");
            
            // Extension DLL one-time initialization
            if (!AfxInitExtensionModule(PluginADLL, hInstance))
                  return 0;

            // Insert this DLL into the resource chain
            // NOTE: If this Extension DLL is being implicitly linked to by
            //  an MFC Regular DLL (such as an ActiveX Control)
            //  instead of an MFC application, then you will want to
            //  remove this line from DllMain and put it in a separate
            //  function exported from this Extension DLL.  The Regular DLL
            //  that uses this Extension DLL should then explicitly call that
            //  function to initialize this Extension DLL.  Otherwise,
            //  the CDynLinkLibrary object will not be attached to the
            //  Regular DLL's resource chain, and serious problems will
            //  result.
 
               //added this line to wizard generated file
            g_hDll = hInstance;

            new CDynLinkLibrary(PluginADLL);
      }
      else if (dwReason == DLL_PROCESS_DETACH)
      {
            TRACE0("PLUGINA.DLL Terminating!\n");
            // Terminate the library before destructors are called
            AfxTermExtensionModule(PluginADLL);
      }
      return 1;   // ok
}

--end file--
Ok, I found it!

The DLL was compiled as MBCS and the client app as UNICODE.  When I switched the DLL to MBCS, I had no problems.

The DLL code was written just as we talked about here, like in AlexFM's first post.

Thanks everyone!

marisa