サービスを停止せずにサーバー プロセスの dll を更新したいと考えています。それ、どうやったら出来るの?asp.net が bin フォルダーに配置された新しい dll を自動的に取得する方法に少し似ています。
3 に答える
Asp.Net はシャドウ コピーと呼ばれる手法を使用します。
更新された dll をアプリケーションの bin サブディレクトリにコピーすると、ASP.NET ランタイムは実行する新しいコードがあることを認識します。ASP.NET は dll を既存の AppDomain にスワップできないため、新しい AppDomain を開始します。古いアプリケーション ドメインは「ドレイン停止」されます。つまり、既存の要求の実行を終了することが許可され、それらがすべて終了すると、AppDomain をアンロードできます。新しい AppDomain は新しいコードで始まり、すべての新しい要求を受け取り始めます。
通常、dll がプロセスに読み込まれると、プロセスが dll をロックし、ディスク上のファイルを上書きできなくなります。ただし、AppDomains にはシャドウ コピーと呼ばれる機能があり、アセンブリをロック解除したままにして、ディスク上で置き換え可能にすることができます。
ランタイムは、bin ディレクトリに対してシャドウ コピーを有効にして ASP.NET を初期化します。AppDomain は、dll をロックしてメモリにロードする前に、必要な dll を bin ディレクトリから一時的な場所にコピーします。シャドウ コピーを使用すると、Web アプリケーションをオフラインにすることなく、更新中に bin ディレクトリ内の任意の dll を上書きできます。
Gulzarの答えに加えて:
サービスが DLL を直接参照しているだけの場合は、AppDomains と ShadowCopy 機能を利用してこの機能を利用するために、サービスを少し再設計する必要があります。
サービスが単なるシェル/ホストプロセスである場合、このようなことを行います。すべての機能は、必要に応じて個別のアプリ ドメインに読み込まれます。
プロセスが dll をロードすると、それを変更することはできません。
IIS は、DLL が使用されていないとき (キャッシュ プロパティの影響を受ける)、メモリにロードされた DLL を保持しません。ASP.NET の場合も同じであると想定しています。同じ戦略に従えば、dll も更新できます。
ただし、dll が使用されている場合は、サーバー プロセスにすべての dll をアンロードするように指示する方法が必要です。
これを行うには、サーバー プロセスは、LoadLibrary 呼び出しを使用してすべての DLL をロードし、そうするように求める通信を受信したときにアンロードできるようにする必要があります。
サーバー プロセスとの通信は、グローバルに使用可能な名前付きイベントを作成することで実行できます。このイベントは、新しいプログラムからアクセスでき、実行中のプロセスに更新が行われることを通知するために使用されます。(これを行う他のバリエーションを考えることもできます)。