Link to home
Start Free TrialLog in
Avatar of mrwad99
mrwad99Flag for United Kingdom of Great Britain and Northern Ireland

asked on

Access violation when creating dialog from dynamically loaded DLL!

Ah hello.

Whilst investigating creation of a dialog class exported from a DLL, I found another problem that I could not solve.

Instead of linking statically to my DLL that contains a CDialog derived class, I tried to dynamically load the DLL.  This I can do: I load my DLL via LoadLibrary, call an exported function to return a new instance of my dialog class, then Create() the dialog in my calling EXE.  However, I am finding that I get an immediate access violation within WinCore.cpp.

Obviously something is messed up with the messaging subsystem, caused by this dialog being created in my DLL.

Can someone suggest what the problem could be please?

Sample project at http://www.yousendit.com/download/OHo0b24ycWZRWUpFQlE9PQ

TIA
Avatar of pgnatyuk
pgnatyuk
Flag of Israel image

This design does not fit.
You need to make an exported function that will fully handle your dialog - call DoModal from this function. So from the executable you will call only this function and see your dialog working.
You may need to worry about the resources with - AFX_MANAGE_STATE in the beginning of this exported function:
http://msdn.microsoft.com/en-us/library/ba9d5yh5(VS.80).aspx
This article is about an old version of studio, but you'll see the approach:
DLL Tutorial : Export a dialog from an Extension DLL
http://www.dotnetheaven.com/Uploadfile/mahesh/DllTutorialDialog05192005012433AM/DllTutorialDialog.aspx

Export dialogs in MFC Extension DLLs
http://www.codeguru.com/cpp/w-p/dll/article.php/c107

MFC .DLL TUTORIAL, PART 3
http://www.codeguru.com/Cpp/Cpp/cpp_mfc/tutorials/article.php/c4023

Here is an MSDN explanation
Export and Import Using AFX_EXT_CLASS
http://msdn.microsoft.com/en-us/library/aa278937(VS.60).aspx
 
Avatar of mrwad99

ASKER

Thanks for the comment.

I don't want to make a modal dialog; I want to make a dialog that I position over my main parent dialog as a sort of "plug-in".  Creating a modal dialog is easy, as you say, DoModal() is called from within the exported function and everything just works.  However, when I call Create() I still get the access violation.

Any suggestions?
Avatar of mrwad99

ASKER

(Oops, did not see the above comment; reading it now.  Will come back with any more questions after reading if necessary )
Avatar of mrwad99

ASKER

OK.  Those links do not help I am afraid; they all refer to static linking via a lib.  I need to dynamically load the DLL, then create the dialog from a function pointer obtained via GetProcAddress().

Do you know how to do this?
I've told you: http::/#a31382406
You can have a function that will create the dialog, another function that will show it, another function will destroy it. You may have a lot of of problems in this way. The modal dialog is much easier.
Another way - use COM. You choose.
Avatar of mrwad99

ASKER

Yes, I know you have told me.  You have said that I need to have a function creating, showing and destroying my dialog.

I have done this; in fact I did all this before I even posted the question.  Your first comment made me change my code slightly to try and Create() the dialog in my DLL's function.

However, this is still not working.  All the calls work fine, but as soon as I resume the debugger, after stepping through the exported DLL function, I get this access violation.

That is what I am stuck on.  Now, if you don't have any suggestions as to what may be causing that, I would ask you to elaborate on your 'use COM' suggestion.

Could you do this please?
COM will bring new difficulties for you, if you've never used it.

I do not understand where you stuck, you need to add more details. I do not see your code. I even didn't understand this kind of game - "Your first comment made me..." :( Let's leave it.

So what you have right now: what is in your DLL - which function, what it does, where is the dialog resources.

I can guess, I think that you have a DLL with an exported function that creates a standard MFC Dialog. If you have DoModal in this function, your application should work technically correctly. Please check this point. If the app does not crash, you may continue and add two other functions into your DLL - for example: ShowMyDialog and CloseMyDialog.

In the DLL, in the cpp-file, add a pointer to this dialog like CMyDialog* s_pMyDlg. It is a static variable initialized with NULL in the beginning. In ShowMyDialog you need to call new CMyDialog, then s_pMyDlg->Create. In the CloseMyDialog you check if s_pMyDlg is not NULL, you close the dialog, delete m_pMyDlg and set it to NULL again.

You may need AFX_MANAGE_STATE(AfxGetStaticModuleState()); in these functions.
The simplest case with DoModal may look so:

int ShowMyDialog()
{
   AFX_MANAGE_STATE(AfxGetStaticModuleState());
   CMyDialog dlg;
   dlg.DoModal();
   return 0;
}

(This code may cause a problem, you can try it yourself and you'll see how it works)

Here is an example with the dialog that is loaded from the DLL exactly as you want:
CodeGuru. Countdown Dialog DLL
http://www.codeguru.com/cpp/w-d/dislog/progressindicators/article.php/c4961

This article is exactly as you need:
CodeProject. Load a child dialog from a dynamic DLL
http://www.codeproject.com/KB/dialog/LoadChild_gunman.aspx

I wish you good luck! Have a nice weekend.



Avatar of AndyAinscow
>> then Create() the dialog in my calling EXE

Am I correct with the following?  (If yes then I think pgnatyuk misunderstands what you want).
I think you want the dialog to be created as a child of another dialog, dynamically with Create not DoModal, and the dialog should be either an independant popup or fixed onto the parent (eg. something like a property page in a property sheet)
I understand it correctly. I proposed to start from the simple DoModal, see that it works and then modify.
Avatar of mrwad99

ASKER

Both, as soon as I have closed off http:Q_26025213.html I will be back here.  I am afraid I tend to ask questions as soon as they arise...
Avatar of mrwad99

ASKER

Right.  I have uploaded the tiny project to https://www.yousendit.com/download/OHo3S3d1ZDUyWGV4dnc9PQ.  The best way to see the code is to take a look at it.  However, I post the most relevant code below, with comments about what happens

In a nutshell:

I participated in a question that I thought was initially answered by myself until the questioner bought a new requirement to light.  It was how a dialog that resides in a DLL can be created over a parent dialog in an executable.  The solution to that was simple: export a dialog class in the DLL and create it over a placeholder control on the main executable.

The questioner then said that whereas this worked, the DLL had to be dynamically loaded.  Now, we cannot create a class instance in the same way as before.  The way to to do it is to export a function from the DLL that does the creation of the dialog class, then return this object back to the executable.  Because of the chance of different CRTs, a cleanup method should be provided in the DLL to free the memory of the dialog.  This was all done without problem.

However, it is now being found that whereas the dialog is created perfectly well, the application soon blows up with an access violation in wincore.cpp;  this appears to be message map related.

Key points:

pgnatyuk:

I appreciate the time you have spent trying to help.  Let me first clarify some points.

1) I can get this working perfectly fine (before I even asked this question, in fact) using a Modal dialog.  However, for the purposes of this question, *the dialog that is to be loaded from the DLL *will not be modal**.  Therefore, I will not be calling DoModal() on it.  It has to be created as a child of the executable's main window.  See the screenshot below.

2) You have posted a link to a codeproject article: "LoadChild_gunman.aspx".  I too have seen this, but was sorely disappointed to find that it does not work.  There are some comments that include what seems to be a hack that claim to be able to get it to work, but that is severely flawed.

Andy:

Yes, that is what I am after.

Can someone advise on how to do this, or why I am getting the access violation *please*?
/*
Shown below is my code as-is.  What happens is that when stepping through the code in the debugger, I get right through to the end of CreateDialogInDLL(), I see the dialog created over the parent dialog (allbeit in the incorrect place, but that is not of concern now).  I then resume application execution and it immediately has an access violation.
*/

// This is the function in the DLL that creates and returns
// a pointer to my dialog.  The only reason we return a pointer is
// so the calling code can reposition the dialog if required.
CDialogInDLL* CreateDialogInDLL(CWnd* pParent)
{
	CDialogInDLL* pwndDlg = new CDialogInDLL();
	if ( pwndDlg )
	{
		BOOL bCreated = pwndDlg->Create ( pParent ); ASSERT ( bCreated );
		if ( !bCreated ) 
		{
			delete pwndDlg; return NULL;
		}
		else
		{
			pwndDlg->ShowWindow(SW_SHOW);
		}
	}	
	return pwndDlg;
}

// This is the calling code trying to create the dialog from the DLL.
// Note: m_pwndChildDlg  is a member variable of type CDialogInDLL
void CTestEXEDlg::OnBnClickedButtonCreate()
{
	if ( HMODULE hMod = ::LoadLibrary ( "DLL.dll" ) )
	{
		if ( PFUNC_CREATE_DIALOG_IN_DLL pFunc = ( PFUNC_CREATE_DIALOG_IN_DLL ) ::GetProcAddress ( hMod, "CreateDialogInDLL" ) )
		{
			m_pwndChildDlg = (*pFunc)(this);
	
		}
		::FreeLibrary ( hMod );
	}
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of pgnatyuk
pgnatyuk
Flag of Israel image

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
I see your project. DLL.h looks ugly. You have to make it simple and standard. For example you don't need the typedef (it should be in the executable).
Why you need CDialogInDLL* exported?
You may need the window handle.
Avatar of mrwad99

ASKER

OK.  Those errors I made are very silly; thank you for pointing them out.

I no longer release the library as stated, and it no longer has an access violation.  You are right in that I don't need to export the class library either.

I will keep the typdef statements in DLL.h though; it provides an easy way for the user to access the functionality of the dynamically loaded functions.

I have posted a new project to the question which I am participating in which led me to ask this question: pgnatyuk, please comment on this question (http:Q_25752850.html) so you can get your share of the points for helping solve the original question.

Thank you very much :o)
You are welcome. Nice to talk with you. I'm glad that my comments helped you.