Donnerstag, 18. September 2008

Invalid String Binding with MFC mixed-mode DLL

Today I was trying to create a mixed-mode DLL which also uses MFC internally. But whenever the application was shut down, an 'invalid string binding' exception was thrown, after which, the process couldn't be killed.

It took me a while to figure out the reason. I already knew that global objects in a mixed-mode DLL could lead to that exception in some circumstances, and that's also the case here. It is thrown in the destructor of the MFC module state object, which is global in each MFC DLL. Some googling provided the info that the exception comes if something tries to access the .NET framework after it has been unloaded.

In this case, the access came from the MFC control container (I was using a CWinFormsControl in the DLL). This in turn was destructed through a CWnd, which was in the temporary MFC handle map. That map should be cleaned up in the 'OnIdle' procedure of MFC applications according to MSDN, but the DLL function is not called automatically (you have to call it yourself from the main application OnIdle through an exported function), and there is one map per module, not a map for all all modules. Anyway, relying on an OnIdle to have been called before the application is shut down is kind of brittle.

So my recommendation - and the fix in my case - is not to use temporary CWnd objects (remember, those are created through CWnd::FromHandle), but to use only CWnd::FromHandlePermanent and CWnd::Attach in mixed-mode MFC DLLs.