EEFileLoadException при использовании классов C # в C ++ (приложение win32) - PullRequest
27 голосов
/ 18 сентября 2008

По причинам развертывания я пытаюсь использовать IJW для переноса сборки C # в C ++ вместо использования COM Callable Wrapper.

Я делал это в других проектах, но в этом я получаю исключение EEFileLoadException. Любая помощь будет оценена!

Управляемый код оболочки C ++ (находится в 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);
}

Тестовый код (это 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;
}

Для чего стоит журнал событий сообщает следующее: .NET Runtime версия 2.0.50727.143 - Неустранимая ошибка двигателя выполнения (79F97075) (80131506)

К сожалению, Microsoft не располагает информацией об этой ошибке.

Ответы [ 6 ]

32 голосов
/ 19 сентября 2008

Проблема заключалась в том, где были расположены библиотеки DLL.

  • C: \ DLLs \ managed.dll
  • C: \ DLLs \ wrapper.dll
  • C: \ EXE \ my.exe

Я подтвердил это, скопировав managed.dll в c: \ exe, и это сработало без проблем. Очевидно, CLR не будет искать управляемые библиотеки DLL в пути неуправляемой библиотеки DLL и будет искать ее только там, где находится исполняемый файл. (или в GAC).

По причинам, не заслуживающим внимания, мне нужна именно эта структура, что означало, что мне нужно было помочь CLR найти управляемую DLL. Смотрите код ниже:

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;
    }
}
9 голосов
/ 18 сентября 2008

Первая проблема - убедиться, что для типа отладчика задан смешанный тип. Тогда вы получите полезные исключения.

4 голосов
/ 30 июля 2015

Для вашего собственного приложения, использующего смешанный режим dll (Ваш EXE), измените ** «Тип отладчика» на «Смешанный» режим. (Перейдите в Свойства проекта -> Свойства конфигурации -> Отладка)

Есть некоторые другие моменты (которые могут быть не важны для вас), но, по моему опыту, они могут вызвать проблемы. - На Windows 8 (с более жесткой безопасностью), пожалуйста, попробуйте запустить VS как администратор. - Убедитесь, что для конфигурации x86 вы используете двоичные файлы x86. - Следите за проверкой StrongName, если ваши сборки C #, которые вы используете в Managed C ++, как подписанные, рассмотрите возможность подписания dll в смешанном режиме.

Надеюсь, это поможет.

1 голос
/ 20 июля 2013

Если кто-то еще наткнется на этот вопрос, и вы используете динамическое имя сборки: убедитесь, что вы удаляете имя сборки, оно может содержать версию, культуру и другой контент, который вы не можете использовать.

Т.е. ваш MyResolveEventHandler должен иметь вид:

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;
}
0 голосов
/ 24 октября 2016

Во время отладки приложения ASP.NET MVC я часто получал CEF EEFileLoadException, генерируемый iisexpress.exe. Стек вызовов и само исключение C ++ не очень помогли мне выявить проблему.

Посмотрев непосредственно на адрес указателя, указанный в исключении C ++, я в конечном итоге обнаружил строку библиотеки, которая указывала на старую версию, которая больше не используется. Это, в свою очередь, было связано с устаревшей записью в моем файле 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>

Я обновил различные библиотеки безопасности Microsoft.Own через NuGet до версии 4.0.30319, но эта строка в конфигурации указывала серверу перенаправлять вызовы до версии 3.0.1.0, которая больше не была частью моего проекта. Обновление конфига решило мои проблемы.

0 голосов
/ 12 января 2011

Когда вы запускаете в отладчике C ++ собственный проект, который использует dll, управляемую C ++, вы можете получить это исключение. Когда VS2010 перехватит его и ваше приложение после некоторых цепных исключений будет прервано, вы можете попробовать в фильтре исключений (Menu | Debug | Excpetion) отключить все исключения C ++. Вы по-прежнему будете видеть это исключение в выходных данных, но ваше приложение не будет прервано

...