Pergunta

Por razões de implantação, eu estou tentando usar IJW para embrulhar um C # montagem em C ++ em vez de usar um Callable Wrapper COM.

Já fiz isso em outros projetos, mas em um presente, eu estou recebendo um EEFileLoadException. Qualquer ajuda seria apreciada!

C ++ invólucro código Controlados (isto é, em uma 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);
}

Code Test (este é um 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 que vale a pena, o log de eventos informa o seguinte: .NET Runtime versão 2.0.50727.143 - Erro do motor Execução Fatal (79F97075) (80131506)

Infelizmente, a Microsoft não tem informações sobre esse erro.

Foi útil?

Solução

O problema era onde as DLLs foram localizados.

  • c: \ DLLs \ managed.dll
  • c: \ DLLs \ wrapper.dll
  • c: \ exe \ my.exe

Eu confirmei isso copiando managed.dll em c: \ exe e ele funcionou sem problema. Aparentemente, o CLR não vai olhar para DLLs geridos no caminho da DLL não gerenciado e só vai olhar para ele, onde o executável é. (Ou no GAC).

Por razões não vale a pena indo para, este é o que eu preciso estrutura, o que significava que eu precisava para dar o CLR uma mão na localizado a dll gerido. Ver código abaixo:

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;
    }
}

Outras dicas

A primeira questão é se certificar que o tipo depurador está definido para misto. Então você começa exceções úteis.

Para você aplicativo nativo consumindo o dll modo misto (seu EXE), altere o ** "Debugger Type" para o modo "misto". (Vá para Propriedades do projeto -> Propriedades de configuração -> Depuração)

Há alguns outros pontos (que pode não ser relevante para você), mas na minha experiência, eles poderiam causar problemas. - No Windows 8 (com maior segurança) por favor tente lançar o seu VS como admin. - Certifique-se de que para a configuração x86 você estiver usando binários x86. -. Relógio para verificação StrongName, se seus # montagens C que você está consumindo em Managed C ++ como assinado, por favor considere assinar o modo dll mista demasiado

Espero que isso ajudaria.

Em caso de alguém se depara com esta questão, e você estiver usando um nome conjunto dinâmico:. Verifique se você está tirando o nome do assembly, pode conter versão, cultura e outros conteúdos que você não pode usar

.

ou seja, o seu MyResolveEventHandler deve ser na 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;
}

Eu estava recebendo o ++ EEFileLoadException C jogado um monte de iisexpress.exe durante a depuração de uma aplicação ASP.NET MVC. A pilha de chamadas e da própria exceção C ++ não eram terrivelmente útil para ajudar me fixar para baixo o problema.

Depois de olhar diretamente para o endereço ponteiro dada no C ++ exceção que eu finalmente descobri uma corda biblioteca que estava apontando para uma versão antiga não está mais em uso. Este por sua vez foi devido a uma entrada out-of-date no meu arquivo 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>

Eu tinha atualizado várias bibliotecas de segurança Microsoft.Own via NuGet para a versão 4.0.30319 mas esta linha na configuração estava instruindo o servidor para redirecionar as chamadas para a versão 3.0.1.0, que agora já não faz parte do meu projeto. Atualizando a configuração resovled meus problemas.

Quando você executa no depurador C ++ projeto nativa que uso C ++ gerenciado dll você pode obter essa exceção. Quando VS2010 pegá-lo e sua aplicação depois de algumas exceções cadeia será abortado você pode tentar no filtro de exceção (Menu | Debug | excpetion) desativar todas as exceções C ++. Você ainda verá essa exceção na saída, mas a sua aplicação não vai abortar

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top