2012-04-04 28 views
10

別のC++ DLLを使用するC#プラグインがあります。そのDLLへの唯一の参照は、プラグイン自体からのものです。親アプリケーションは、すべてのプラグインを独自のAppDomainにロードし、プラグインがアンロードされるとこのAppDomainをアンロードします。C++ DLLがAppDomainでアンロードされない

私はプラグインをアンロードすると、アプリケーションのメモリが低下していることを確認しました。私は、ロードされたすべてのマネージアセンブリを削除することもできます。問題は、ネイティブDLLを削除しようとすると、アプリケーション全体を閉じるまで、アクセス拒否が発生し続けるということです。

私はこれをしばらく見てきましたが、このDLLがなぜメモリに残っているのかまだ分かりません。

答えて

18

AppDomainsは、純粋なマネージドコード構造です。そのようなものはネイティブコードには存在しませんし、Windowsにはそれに関する考えもありません。したがって、ロードされたネイティブDLLのスコープがプロセスです。技術的には、pinvoke marshallerがDLLのカウントを参照し、DLLのロードを引き起こしたAppDomainを正確に追跡することができます。ただし、そのDLLを使用するネイティブコードが実行されているかどうかはわかりません。 AppDomainのコードから呼び出された呼び出しによって開始されるネイティブコード。おそらく間接的にマーシャリングされたデリゲートを介して呼び出されます。

明らかに、AppDomainマネージャがそのように使用されているDLLをアンロードすると、災害が発生します。これは、アクセス違反を診断するのは厄介で不可能です。 AppDomainがアンロードされた後、長い時間がかかる可能性があるため、特に厄介です。

marshallerはこの種のカウントを実装していないので、DLLはロードされたままです。 DLLで実行されているコードとその起動方法を正確に制御する手段があります。 にDLLを強制的にアンロードしますが、ハックが必要です。 DLLのハンドルを取得するには、LoadLibrary()を自分で行います。そして、FreeLibrary()を2回に強制して強制的にアンロードしてください。 WindowsとCLRのどちらも、あなたが不正行為をしていることを知ることはできません。 で、この後にDLLを使用できないようにする必要があります。

+3

+1いいえハック:-) – Yahia

+0

ねえ、ちょうど非常に明確な答えに感謝したいと思っていました! – user472875

5

私の知る限り(ボンネットの下)は、ネイティブのDLLがプロセスメモリに直接それらをロードするWin32 API LoadLibrary ...を介してロードする必要がある - AppDomainに固有ではない.NETアプリケーションの場合には... LoadLibraryおよそAppDomain(純粋な.NET固有である)絶対に何も知らない...これAppDomainをアンロードすることは必ずしもネイティブのDLLをアンロードしません...このような状況に関する

興味深い議論:

あなたは、各プラグインの実装を変更することができる場合、あなたはあなたが見る問題解決するだろう「後半ネイティブ結合」を実装します:

関連する問題