C # .NET Control de usuario dentro de la aplicación nativa. Problemas de la cadena de recursos
Estoy terminando una extensión MFC DLL (MFCXDLL_2) para que su funcionalidad esté disponible para los programadores de C #.
El contenedor es una "DLL regular que utiliza una DLL MFC compartida" con "Common Language Runtime Support (/ clr)". (Modo mezclado)
Las clases en MFCXDLL_2 que estarán disponibles están decoradas en MFCXDLL_3.
El escenario que estoy experimentando es el caso en que MFCXDLL_2 se usa desde un control de usuario C # .NET que se ejecuta en una aplicación nativa.
Otra extensión MFC DLL -MFCXDLL_1-dentro de la aplicación nativa también usa el MFCXDLL_2 y esto causa problemas.
Cuando inicio la aplicación nativa, cargará implícitamente el MFCXDLL_2.
Cuando cargo el control de usuario .NET, el mismo MFCXDLL_2 se vuelve a cargar explícitamente de acuerdo con el consejo enhttp: //msdn.microsoft.com/en-us/library/ksa99t88.asp, "Uso de DLL de base de datos, OLE y extensión de sockets en DLL normales".
anto el código nativo como el control de usuario .NET crean instancias del mismo tipo de clase y llaman al mismo método en MFCXDLL_2.
El método deserializa los datos (recibidos en la memoria compartida) y devuelve los datos deserializados a la persona que llama. Esto funciona muy bien desde el código nativo hasta que cargue el control de usuario .NET.
Después de cargar el control de usuario .NET, la deserialización deja de funcionar desde el código nativo, pero funciona muy bien cuando se llama desde el control de usuario .NET.
Adjunté WinDbg a la versión de depuración de la aplicación nativa y ejecuté mi escenario. WinDbg encontró lo siguiente durante la deserialización:
"Advertencia: no se puede cargar desde el archivo. Clase no definida. Excepción de archivo: badClass ”.
Creo que hay algunos problemas de recursos aquí, así que ejecuto la versión de lanzamiento de la aplicación nativa cargando la versión de lanzamiento de MFCXDLL_2. Luego cargo la versión de depuración del control de usuario .NET, que nuevamente carga la versión de depuración de MFCXDLL_2 en la aplicación nativa.
Entonces todo funciona muy bien. Una versión de lanzamiento de MFCXDLL_2 cargada por el código nativo y una versión de depuración de MFCXDLL_2 cargada por el control de usuario de .NET, todo ejecutado dentro de la aplicación nativa.
Entonces, ¿qué está pasando? ¿No es posible acceder al mismo MFCXDLL desde, p. una DLL de extensión y una DLL normal al mismo tiempo en la misma aplicación?
¿Se destruye la cadena de recursos de alguna manera? ¿Cuáles son las posibles soluciones
Aquí hay un código que muestra cómo se carga la DLL MFCXDLL_2
Cuando se inicia la aplicación nativa MFCXDLL_2 DLLMain se llama:
static AFX_EXTENSION_MODULE MFCXDLL_2 = { NULL, NULL };
static CDynLinkLibrary* gpDynLinkLibrary = NULL;
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID )
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// Extension DLL one-time initialization
AfxInitExtensionModule(MFCXDLL_2, hInstance);
// Insert this DLL into the resource chain
gpDynLinkLibrary = new CDynLinkLibrary(MFCXDLL_2);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
if (gpDynLinkLibrary)
{
delete gpDynLinkLibrary;
gpDynLinkLibrary = NULL;
}
// Terminate the library before destructors are called
AfxTermExtensionModule(MFCXDLL_2);
}
return 1; // ok
}
Cuando se carga el control de usuario .NET, la DLL MFCXDLL_2 se vuelve a cargar:
//==============================================================
// Exported DLL initialization to run in context of Regular DLL.
// Must be called in InitInstance
// BOOL CYourRegularDLLApp::InitInstance()
//==============================================================
extern "C" _declspec(dllexport) CDynLinkLibrary* WINAPI InitMFCXDLL_2FromRegularDLL()
{
if (gpDynLinkLibrary)
{
delete gpDynLinkLibrary;
gpDynLinkLibrary = NULL;
}
// Create a new CDynLinkLibrary for this Regular DLL
return new CDynLinkLibrary(MFCXDLL_2);
}
El código de deserialización dentro de MFCXDLL_2
CMyClass* pMyclass = NULL; //CObject derived serializeable class
BYTE *pBuf = pGlobalCom->GetBuffer(); //Buffer with serialized CMyClass
int nBufSize = pGlobalCom->GetSize(); //Size of buffer
CMemFile mf;
mf.Attach(pBuf,nBufSize);
CArchive ar(&mf, CArchive::load); //“Warning: Cannot load CMyClass from archive. Class not defined.CArchive exception: badClass.”
ar >> pMyclass; //CArchive exception thrown
ar.Close();
mf.Detach();
La imagen muestra la relación entre los dlls.