I have a Visual Studio 2008 solution with two projects: a C# Windows Forms application and a C++ DLL. The DLL opens a custom CFileDialog. Here is a toy version that demonstrates the problem, where the C# app is just a button to launch the dialog and a label to show its result:
DialogApp.cs:
...
public partial class Form1 : Form {
...
[DllImport("DialogDll.dll")]
static extern int OpenDialog();
...
private void button1_Click(object sender, EventArgs e) {
int r = OpenDialog();
label1.Text = r.ToString();
}
}
DialogDll.h:
extern "C" {
__declspec(dllexport) int __cdecl OpenDialog();
}
DialogDll.cpp:
#include <afxdlgs.h>
#include "DialogDll.h"
extern int __cdecl OpenDialog() {
CFileDialog d(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("All F开发者_如何学JAVAiles (*.*)|*.*||"), NULL);
if (d.DoModal() == IFOK) {
return 4;
} else {
return 9;
}
}
When I run this, I get an error about a debug assertion failing, asking to Abort|Retry|Ignore. The assertion is afxCurrentResourceHandle != NULL
. How do I get rid of this problem? If I click Ignore, I get my dialog, and everything appears to work fine.
I've already tried following the instructions here: http://msdn.microsoft.com/en-us/library/7a51wcfx.aspx
These directions say the problem is that a DLL doesn't have a CWinApp object, and I should add AFX_MANAGE_STATE(AfxGetStaticModuleState())
to the beginning of each function call. I did that, and had to resolve a linker issue by following the directions here, manually specifying the entry point for my DLL: http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/0b154e1c-141f-4567-bb24-1ac7c8ee2713/ (The parts about changing the order of the .libs didn't work for me.)
But now I'm getting another error:
LoaderLock was detected:
Attempting managed execution code inside OS Loader Lock. Do not attempt to run
managed code inside a DllMain or image initialization function since doing so
can cause the application to hang.
Good grief! Am I even going in the right direction? I've done years of programming, but I'm pretty new to the Windows platform. I think after all this work, my question is still pretty simple: How do I open a CFileDialog from my dll?
You are probably going in the right direction. I am assuming that you want/need to use MFC in your DLL.
The WinApp and MANAGE_STATE advice was good.
Are you throwing /clr or /clr:pure on any of your C++ source files? Why? Does your C++ DLL mix managed and native code together?
The fix for this trivial app is to not throw /clr. This will make all your C++ code native and ensure that you are not at risk of calling managed static initialisers from the loader lock.
Martyn
Please see comment above, but I would recommend as my answer:
Use System.Windows.Forms.OpenFileDialog instead OR
Use GetOpenFileName
精彩评论