29

展開上の理由から、COM Callable Wrapper を使用する代わりに、IJW を使用して C# アセンブリを C++ でラップしようとしています。

私は他のプロジェクトでそれを行いましたが、このプロジェクトでは 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 ランタイム バージョン 2.0.50727.143 - 致命的な実行エンジン エラー (79F97075) (80131506)

残念ながら、マイクロソフトはそのエラーに関する情報を持っていません。

4

6 に答える 6

35

問題は、DLL が配置されている場所でした。

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

managed.dll を c:\exe にコピーしてこれを確認したところ、問題なく動作しました。どうやら、CLR はアンマネージ DLL のパスでマネージ DLL を検索せず、実行可能ファイルがある場所のみを検索します。(またはGACで)。

踏み込む価値のない理由により、これは私が必要とする構造です。つまり、マネージド DLL を見つけるために CLR に手を貸す必要がありました。以下のコードを参照してください。

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

};

ラッパー.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;
    }
}
于 2008-09-18T20:36:41.560 に答える
10

最初の問題は、デバッガーの種類が混合に設定されていることを確認することです。次に、有用な例外を取得します。

于 2008-09-18T16:44:00.840 に答える
5

混合モードの dll (お使いの EXE) を使用するネイティブ アプリケーションの場合、**"Debugger Type" を "Mixed" モードに変更します。(プロジェクト プロパティ -> 構成プロパティ -> デバッグに移動)

他にもいくつかのポイントがあります (あなたには関係ないかもしれません) が、私の経験では問題を引き起こす可能性があります。- Windows 8 (セキュリティが強化されている) では、VS を管理者として起動してみてください。- x86 構成では、x86 バイナリを使用していることを確認してください。- StrongName の検証に注意してください。Managed C++ で使用している C# アセンブリが署名されている場合は、混合モードの dll にも署名することを検討してください。

これが役立つことを願っています。

于 2015-07-30T11:53:20.650 に答える
1

ASP.NET MVC アプリケーションのデバッグ中に、iisexpress.exe によって C++ EEFileLoadException が大量にスローされました。コール スタックと 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>

NuGet を介してさまざまな Microsoft.Own セキュリティ ライブラリをバージョン 4.0.30319 にアップグレードしましたが、config のこの行は、サーバーに呼び出しをバージョン 3.0.1.0 にリダイレクトするように指示していました。これは、現在プロジェクトの一部ではありません。構成を更新すると、問題が解決しました。

于 2016-10-24T16:47:50.547 に答える
1

他の誰かがこの質問に遭遇し、動的アセンブリ名を使用している場合: アセンブリ名を削除していることを確認してください。アセンブリ名には、使用できないバージョン、カルチャ、およびその他のコンテンツが含まれている可能性があります。

つまり、 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;
}
于 2013-07-20T12:35:12.323 に答える
-5

C++ マネージ dll を使用するデバッガー C++ ネイティブ プロジェクトで実行すると、この例外が発生する場合があります。VS2010 がそれをキャッチし、一部のチェーン例外が中止された後にアプリケーションが中止されると、例外フィルター (Menu|Debug|Expetion) ですべての C++ 例外を無効にすることができます。この例外は引き続き出力に表示されますが、アプリケーションは中止されません

于 2011-01-11T22:25:39.547 に答える