背景
私はアプリケーションのプラグインを維持しています。Visual C++ 2003 を使用しています。
プラグインは複数の DLL で構成されています。アプリケーションが LoadLibrary を使用してロードするメイン DLL と、メイン DLL および相互に使用されるユーティリティ DLL がいくつかあります。
依存関係は一般的に次のようになります。
- plugin.dll -> utilA.dll、utilB.dll
- utilA.dll -> utilB.dll
- utilB.dll -> utilA.dll、utilC.dll
あなたは絵を手に入れます。
DLL 間の依存関係には、読み込み時と実行時があります。
すべての DLL ファイルは、実行可能ファイルのディレクトリに保存されます (要件ではなく、現在の動作のみです)。
問題
アプリケーション内でプラグインの複数のインスタンスを実行するという新しい要件があります。
アプリケーションはプラグインの各インスタンスを独自のスレッドで実行します。つまり、各スレッドは plugin.dll によってエクスポートされた関数を呼び出します。ただし、プラグインのコードはスレッドセーフではありません - 多数のグローバル変数など..
残念ながら、すべてを修正することは現在のところオプションではないため、同じプロセスでプラグインの DLL の複数 (最大 3 つ) のコピーをロードする方法が必要です。
オプション 1: 個別の名前アプローチ
各 DLL ファイルの 3 つのコピーを作成して、各ファイルが個別の名前を持つようにします。たとえば、plugin1.dll、plugin2.dll、plugin3.dll、utilA1.dll、utilA2.dll、utilA3.dll、utilB1.dll などです。アプリケーションは、plugin1.dll、plugin2.dll、および plugin3.dll をロードします。ファイルは実行可能ファイルのディレクトリにあります。
DLL の各グループが名前で相互に認識できるように (相互依存関係が機能するように)、コンパイル時に名前を認識している必要があります。つまり、DLL を複数回コンパイルする必要がありますが、毎回異なる出力ファイル名を使用する必要があります。
それほど複雑ではありませんが、VS プロジェクト ファイルのコピーを 3 つ持つのは嫌いで、同じファイルを何度もコンパイルする必要はありません。
オプション 2: サイド バイ サイド アセンブリ アプローチ
DLL ファイルの 3 つのコピーを作成し、各グループを独自のディレクトリに作成し、アセンブリ マニフェスト ファイルをディレクトリに配置して各グループをアセンブリとして定義し、プラグインの DLL をリストします。
各 DLL にはアセンブリを指すアプリケーション マニフェストが含まれているため、ローダーは同じディレクトリにあるユーティリティ DLL のコピーを見つけます。LoadLibrary を使用して DLL をロードするときにマニフェストが見つかるように、マニフェストを埋め込む必要があります。VS2003 にはマニフェストの埋め込みサポートが組み込まれていないため、このジョブには新しい VS バージョンの mt.exe を使用します。
私はこのアプローチを試してみましたが、部分的に成功しました.DLLのロード時に依存関係が見つかりましたが、別のDLLをロードするDLL関数が呼び出されたときではありません. この記事
によると、これは予想される動作のようです。DLL のアクティベーション コンテキストは、DLL の読み込み時にのみ使用され、その後は非アクティブ化され、プロセスのアクティベーション コンテキストが使用されます。
編集:期待どおりに動作します-DLLISOLATION_AWARE_ENABLED
のランタイムロードは、ロードDLLの元のアクティブ化コンテキストを使用します。
質問
他に選択肢はありますか? 迅速で汚い解決策は何でも構いません。:-)
ISOLATION_AWARE_ENABLED
VS2003 でも動作しますか? 編集:そうです。
コメントをお待ちしております。
ありがとう!