2011-08-10 18 views
5

私はマネージC++アセンブリを標準のLoadLibrary()呼び出しによってアンマネージC++アプリケーションで動的にロードしています。管理対象のC++アセンブリは、複数の管理対象(C#)アセンブリに依存します。管理されているすべてのアセンブリをアンマネージアプリケーションのサブディレクトリに移動するまでは、すべて正常に機能しました。説明するために:アンマネージC++から混合モードC++/CLIの.dll(および依存関係)を動的にロード

C++の.dll(MyCoolDll.dll)

  • DotNetDll2.dll
  • アンマネージC++アプリケーション(MyCoolAppに依存DotNetDll1.dll

  • に依存して管理
    • を.exe)

      • のロードは、LoadLibrary関数を経由してMyCoolDll.dll私はへ/ someSubDirectory(MyCoolAppのコードMyCoolDll.dll、DotNetDll1.dll & DotNetDll2.dllを移動するまで( "MyCoolDll.dll")

    これは、うまく働きました。 exeがLoadLibrary( "someSubDirectory/MyCooldll.dll")に更新されました

    MyCoolDll.dllが読み込まれたときに、ディレクトリの代わりにDotNetDll1.dllとDotNetDll2.dllを作業ディレクトリに検索しようとしています

    どのようにしてMyCoolDll.dllの依存関係をサブディレクトリに置くことができますか外出?それはアンマネージドアプリケーションの中で実行されているライブラリなので、app.configなどでこれを指定できるとは思いませんか?

  • +1

    うわー、ハンス、うまくいった! MyCoolApp.exeは単純な古いWin32アプリケーション(.NETではなく)なので、私は本当に疑念を抱いていました。ありがとう!コメントではなく答えとして書き留めたいですか?それを受け入れたとマークしますか? – Jordan0Day

    答えて

    5

    CLRはネイティブのエクスポートをコンパイルするとき、コンパイラが注入されたことをサンクによって、このシナリオでは、異常な方法でロードされます__declspec(dllexport)の場合これを行うことは問題ありません。それは特に高速ではありません。

    CLRは、.configファイルを検索してプライマリAppDomainを初期化します。これは管理された実行可能ファイルではないことにかかわらず、MyCoolApp.exe.configを探します。 <probing> elementを使用して、サブディレクトリを追加してアセンブリを検索できます。

    8

    あなたが探しているのはカスタムアセンブリリゾルバだと思います。私はあなたがしようとしていると思うことをするために1つを使用しなければならなかった - 私は最初の管理されていないDLL(マネージコードを最終的にロードした)のツリーになかったフォルダ内のいくつかのDLLを探したい。

    void PrepareManagedCode() 
    { 
        // Set up our resolver for assembly loading 
        AppDomain^ currentDomain = AppDomain::CurrentDomain; 
        currentDomain->AssemblyResolve += gcnew ResolveEventHandler(currentDomain_AssemblyResolve); 
    } // PrepareManagedCode() 
    

    その後リゾルバ:

    ステップ1リゾルバを設定するために呼び出すことができる機能を作ることです。この例では、あなたのケースでは、あなたが使用していた余分なフォルダになりグローバルourFinalPathがあります

    /// <summary> 
    /// This handler is called only when the CLR tries to bind to the assembly and fails 
    /// </summary> 
    /// <param name="sender">Event originator</param> 
    /// <param name="args">Event data</param> 
    /// <returns>The loaded assembly</returns> 
    Assembly^ currentDomain_AssemblyResolve(Object^ sender, ResolveEventArgs^ args) 
    { 
        sender; 
    
        // If this is an mscorlib, do a bare load 
        if (args->Name->Length >= 8 && args->Name->Substring(0, 8) == L"mscorlib") 
        { 
         return Assembly::Load(args->Name->Substring(0, args->Name->IndexOf(L",")) + L".dll"); 
        } 
    
        // Load the assembly from the specified path 
        String^ finalPath = nullptr; 
        try 
        { 
         finalPath = gcnew String(ourAssemblyPath) + args->Name->Substring(0, args->Name->IndexOf(",")) + ".dll"; 
         Assembly^ retval = Assembly::LoadFrom(finalPath); 
         return retval; 
        } 
        catch (...) 
        { 
        } 
    
        return nullptr; 
    } 
    
    +0

    これは、私がダウンしなければならないと思っていたパスです。問題は、メインのアプリケーションディレクトリにMyCoolDll.dllの依存関係を依頼する必要があるように思えました.netはそれらのサブフォルダを前に検索しないためですMyCoolDllを読み込むことさえできます。dll(アセンブリリゾルバは最初にセットアップされません)。 MyCoolApp.exeは管理された実行可能ファイルではありませんが、上記のHansの提案はうまくいくと思います。 – Jordan0Day

    +0

    アンマネージドDLLは、アセンブリの解決が必要になる前にロードされます。次に、混在モードのDLLを自分でロードし、アセンブリ解決セットアップを呼び出します。複雑なシナリオの場合は、それが必要です。しかし、簡単な設定ファイルがあなたのケースでうまくいくなら、素晴らしい! –

    +0

    私が見ていた問題は、私の混在モードのdllが他のいくつかの.NETアセンブリに依存していたためです。サブフォルダではなくメインディレクトリにこれらの依存関係を置かない限り、実行可能なコードは私の混在モードのDLLをどこにアセンブリのリゾルバを配線することができます。 – Jordan0Day

    関連する問題