c# managed-c++

EEFileLoadException al usar clases C#en C++(aplicación win32)



managed-c++ (6)

El primer problema es asegurarse de que el tipo de depurador esté configurado como mixto. Entonces obtienes excepciones útiles.

Por razones de implementación, estoy tratando de usar IJW para envolver un ensamblado de C # en C ++ en lugar de usar un Contenedor COM invocable.

Lo hice en otros proyectos, pero en este caso, recibo una EEFileLoadException. ¡Cualquier ayuda sería apreciada!

Código de contenedor administrado de C ++ (esto está en una DLL):

extern "C" __declspec(dllexport) IMyObject* CreateMyObject(void) { //this class references c# in the constructor return new CMyWrapper( ); } extern "C" __declspec(dllexport) void DeleteMyObject(IMyObject* pConfigFile) { delete pConfigFile; } extern "C" __declspec(dllexport) void TestFunction(void) { ::MessageBox(NULL, _T("My Message Box"), _T("Test"), MB_OK); }

Código de prueba (esto es un EXE):

typedef void* (*CreateObjectPtr)(); typedef void (*TestFunctionPtr)(); int _tmain testwrapper(int argc, TCHAR* argv[], TCHAR* envp[]) { HMODULE hModule = ::LoadLibrary(_T("MyWrapper")); _ASSERT(hModule != NULL); PVOID pFunc1 = ::GetProcAddress(hModule, "TestFunction"); _ASSERT(pFunc1 != NULL); TestFunctionPtr pTest = (TestFunctionPtr)pFunc1; PVOID pFunc2 = ::GetProcAddress(hModule, "CreateMyObject"); _ASSERT(pFunc2 != NULL); CreateObjectPtr pCreateObjectFunc = (CreateObjectPtr)pFunc2; (*pTest)(); //this successfully pops up a message box (*pCreateObjectFunc)(); //this tosses an EEFileLoadException return 0; }

Por lo que vale, el Registro de eventos informa lo siguiente: .NET Runtime versión 2.0.50727.143 - Error fatal del motor de ejecución (79F97075) (80131506)

Desafortunadamente, Microsoft no tiene información sobre ese error.


El problema era dónde estaban ubicados los archivos DLL.

  • c: / dlls / managed.dll
  • c: / dlls / wrapper.dll
  • c: / exe / my.exe

Confirmé esto copiando managed.dll en c: / exe y funcionó sin problemas. Aparentemente, el CLR no buscará archivos DLL administrados en la ruta del archivo DLL no administrado y solo lo buscará donde está el archivo ejecutable. (o en el GAC).

Por razones que no vale la pena, esta es la estructura que necesito, lo que significaba que tenía que darle una mano al CLR para ubicar el dll administrado. Vea el código a continuación:

AssemblyResolver.h:

/// <summary> /// Summary for AssemblyResolver /// </summary> public ref class AssemblyResolver { public: static Assembly^ MyResolveEventHandler( Object^ sender, ResolveEventArgs^ args ) { Console::WriteLine( "Resolving..." ); Assembly^ thisAssembly = Assembly::GetExecutingAssembly(); String^ thisPath = thisAssembly->Location; String^ directory = Path::GetDirectoryName(thisPath); String^ pathToManagedAssembly = Path::Combine(directory, "managed.dll"); Assembly^ newAssembly = Assembly::LoadFile(pathToManagedAssembly); return newAssembly; } };

Wrapper.cpp:

#include "AssemblyResolver.h" extern "C" __declspec(dllexport) IMyObject* CreateMyObject(void) { try { AppDomain^ currentDomain = AppDomain::CurrentDomain; currentDomain->AssemblyResolve += gcnew ResolveEventHandler( AssemblyResolver::MyResolveEventHandler ); return new CMyWrapper( ); } catch(System::Exception^ e) { System::Console::WriteLine(e->Message); return NULL; } }


Cuando ejecuta un depurador proyecto nativo de C ++ que utiliza dll administrado C ++ puede obtener esta excepción. Cuando VS2010 lo detecte y su aplicación después de que se cancelen algunas excepciones de la cadena, puede intentar con el filtro de excepciones (Menú | Depurar | Excluir) deshabilitar todas las excepciones de C ++. Todavía verá esta excepción en el resultado, pero su aplicación no abortará


En caso de que alguien más tropiece con esta pregunta, y esté usando un nombre de ensamblado dinámico: asegúrese de quitar el nombre del ensamblado, puede contener versión, cultura y otro contenido que no pueda usar.

Es decir, su MyResolveEventHandler debe tener la forma de:

static Assembly^ MyResolveEventHandler( Object^ sender, ResolveEventArgs^ args ) { Console::WriteLine( "Resolving..." ); String^ assemblyName = args->Name; // Strip irrelevant information, such as assembly, version etc. // Example: "Acme.Foobar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" if( assemblyName->Contains(",") ) { assemblyName = assemblyName->Substring(0, assemblyName->IndexOf(",")); } Assembly^ thisAssembly = Assembly::GetExecutingAssembly(); String^ thisPath = thisAssembly->Location; String^ directory = Path::GetDirectoryName(thisPath); String^ pathToManagedAssembly = Path::Combine(directory, assemblyName ); Assembly^ newAssembly = Assembly::LoadFile(pathToManagedAssembly); return newAssembly; }


Para su aplicación nativa que consume el dll de modo mixto (su EXE), cambie el ** "Tipo de depurador" al modo "Mixto". (Vaya a Propiedades del proyecto -> Propiedades de configuración -> Depuración)

Hay algunos otros puntos (que pueden no ser relevantes para usted) pero en mi experiencia podrían causar problemas. - En Windows 8 (con mayor seguridad) intente iniciar su VS como administrador. - Asegúrese de que para la configuración x86 esté utilizando binarios x86. - Observe la verificación de StrongName, si sus ensamblajes de C # que está consumiendo en Managed C ++ están firmados, considere firmar también el dll de modo mixto.

Espero que esto ayude.


Obtuve mucho C ++ EEFileLoadException lanzado por iisexpress.exe durante la depuración de una aplicación ASP.NET MVC. La pila de llamadas y la excepción de C ++ no fueron terriblemente útiles para ayudarme a identificar el problema.

Después de mirar directamente la dirección del puntero dada en la excepción de C ++, finalmente descubrí una cadena de biblioteca que apuntaba a una versión anterior que ya no se usaba. Esto a su vez se debió a una entrada desactualizada en mi archivo web.config:

<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> </dependentAssembly> </assemblyBinding> </runtime>

Había actualizado varias bibliotecas de seguridad de Microsoft.Own a través de NuGet a la versión 4.0.30319, pero esta línea en la configuración indicaba al servidor que redireccionara las llamadas a la versión 3.0.1.0, que ya no formaba parte de mi proyecto. La actualización de la configuración resolvió mis problemas.