Domanda

Per motivi di distribuzione, sto cercando di utilizzare IJW per racchiudere un assembly C# in C++ invece di utilizzare un COM Callable Wrapper.

L'ho fatto su altri progetti, ma su questo ricevo un'EEFileLoadException.Qualsiasi aiuto sarebbe apprezzato!

Codice wrapper C++ gestito (si trova in 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);
}

Codice di prova (questo è 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;
}

Per quello che vale, il registro eventi riporta quanto segue:.NET Runtime Versione 2.0.50727.143 - Errore del motore di esecuzione fatale (79f97075) (80131506)

Sfortunatamente, Microsoft non ha informazioni su quell'errore.

È stato utile?

Soluzione

Il problema era dove si trovavano le DLL.

  • c:\dlls\gestito.dll
  • c:\dlls\wrapper.dll
  • c:\exe\mio.exe

L'ho confermato copiando Managed.dll in c:\exe e ha funzionato senza problemi.Apparentemente, CLR non cercherà le DLL gestite nel percorso della DLL non gestita e le cercherà solo dove si trova l'eseguibile.(o nel GAC).

Per ragioni che non vale la pena approfondire, questa è la struttura di cui ho bisogno, il che significa che dovevo dare una mano a CLR per individuare la DLL gestita.Vedi il codice qui sotto:

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

Altri suggerimenti

Il primo problema è assicurarsi che il tipo Debugger sia impostato su misto.Quindi ottieni eccezioni utili.

Per l'applicazione nativa che utilizza la DLL in modalità mista (il tuo EXE), modifica **"Tipo di debugger" in modalità "Mista".(Vai a Proprietà del progetto -> Proprietà di configurazione -> Debug)

Ci sono altri punti (che potrebbero non essere rilevanti per te) ma secondo la mia esperienza potrebbero causare problemi.- Su Windows 8 (con maggiore sicurezza) prova ad avviare VS come amministratore.- Assicurati che per la configurazione x86 utilizzi i binari x86.- Controlla la verifica di StrongName, se i tuoi assembly C# che stai utilizzando in Managed C++ sono firmati, considera di firmare anche la DLL in modalità mista.

Spero che questo possa essere d'aiuto.

Nel caso in cui qualcun altro si imbatte in questa domanda e stai utilizzando un nome di assembly dinamico:assicurati di eliminare il nome dell'assembly, potrebbe contenere versione, cultura e altri contenuti che potresti non utilizzare.

Cioè, il tuo MyResolveEventHandler dovrebbe essere sotto forma di:

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

Ricevevo spesso l'EEFileLoadException C++ lanciata da iisexpress.exe durante il debug di un'applicazione ASP.NET MVC.Lo stack di chiamate e l'eccezione C++ stessa non sono stati di grande aiuto nell'aiutarmi a definire il problema.

Dopo aver esaminato direttamente l'indirizzo del puntatore fornito nell'eccezione C++, alla fine ho scoperto una stringa di libreria che puntava a una vecchia versione non più in uso.Ciò a sua volta era dovuto a una voce non aggiornata nel mio file 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>

Avevo aggiornato varie librerie di sicurezza Microsoft.Own tramite NuGet alla versione 4.0.30319 ma questa riga nella configurazione indicava al server di reindirizzare le chiamate alla versione 3.0.1.0, che ora non faceva più parte del mio progetto.L'aggiornamento della configurazione ha risolto i miei problemi.

Quando esegui un progetto nativo C++ del debugger che utilizza la DLL gestita da C++, potresti ottenere questa eccezione.Quando VS2010 lo rileva e la tua applicazione dopo che alcune eccezioni di catena verranno interrotte, puoi provare nel filtro delle eccezioni (Menu | Debug | Excpetion) a disabilitare tutte le eccezioni C++.Vedrai ancora questa eccezione nell'output ma la tua applicazione non verrà interrotta

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top