プロセス終了時にリソースの割り当てを解除する
-
20-08-2019 - |
質問
プロセスがタスク マネージャーなどによって強制終了された場合、リソースの割り当てを解除するにはどうすればよいですか?プロセスが閉じられる前に関数を呼び出す方法はありますか?
解決
本当にあなたのプロセスが殺されている場合、あなたができることは何もありません。定義では、プロセスを殺すことはそういうことだ - それを殺します。プロセスは、任意のコードを実行する機会を得ることはありません。これは非常に「デザインによって」です。
あなたのプロセスがユーザによって(または別のプロセスによって)殺されたときに呼び出されたルーチンを登録することができることを想像してみてください。それは何をしますか?あなたのプロセス内の他のすべてのスレッドが不確定な状態になり、あなたは彼らとどのように同期させるのでしょうか?覚えておいてください、アイデアは、プロセスが殺される必要があるということです。
他のシナリオでも厳しいです:あなたのコードは、良性と正しいことをやろうとしている - 例えばクリーンアップと良いシステム市民も。いくつかのコードではありません。 OSは、コードが殺されていたプロセスのために実行することが許可されている場合、マルウェアの作者への恩恵は、それがどうなるか想像してみてください。これは、管理者権限で実行中のすべてのための標準的なユーザー権限で実行していた悪質なプロセスのために十分に悪い、と完全にひどいだろう。
クリティカルが確定し、構造化例外処理は、この根本的な問題を解決することはできません。
上側に、OSは、それはあなたのプロセスが殺されたときに知っているすべてのリソース、すなわちメモリおよびカーネルオブジェクトが解放されます。これらは、リークされません。それはそれのためにクリーンアップすることはできませんので、しかし、エクスプローラは、あなたのプロセスについて知りません。
これを解決する1つの方法は、あなたの他のプロセスの状態を追跡し、それをクリーンアップする監視プロセスを持っているだろう。あなたは、単純なプロセスで、またはサービスでこれを行うことができます。また、同じことをした独自のスレッドを持っていたシェル拡張のいくつかの種類を考えるかもしれません。
他のヒント
このようなタスクマネージャによってようTerminateProcess
への呼び出し、またはそのようなTSKILL又はTASKKILLなどの他のプロセスユーティリティによって殺されようとしているプロセス内の終了時に任意のコードを実行する方法はありません。
重要なファイナライザ、また通常のファイナライザのいずれも、またブロック最後に/してみてください、と確かにIDisposable
を実装していない単なるオブジェクトコードは、このシナリオで実行される可能性があります。でも、DLLのイベントがTerminateProcess
を介してプロセスの終了から呼び出されることはありません切り離します。
あなたができる最善のは、元のプロセスを監視し、元のプロセスが終了したときに、関連するコードを実行し、ウォッチドッグ・プロセスを使用することです。
理論的には、プロセスが強制終了された後、O/S はリソースの割り当てを解除する必要があります。具体的にはどのようなリソースを考えていますか?
編集:
わかりました、説明するのは少し難しいです。いくつかのシェル拡張機能を管理するために、いくつかの OS 関数をラップするライブラリを使用しています。適切なメソッドを明示的に呼び出さずにアプリケーションを閉じると、すべてのエクスプローラーがフリーズし、再起動する必要があります。
アンマネージ DLL は (ドキュメントによると) で呼び出されることになっています。 DLL_PROCESS_DETACH
イベント;ただし、これ DLL_PROCESS_DETACH
プロセスが終了した場合、イベントは呼び出されません。 TerminateProcess
API。
グーグルで検索 これらの用語 起きた 古くて新しいもの :TerminateProcess をトラップできないのはなぜですか?それは、「TerminateProcess で強制終了すると、そのプロセスではユーザー モード コードは実行されなくなります。なくなってしまった。"
なぜなら、あなたが扱おうとしているすべてのもの(すなわち、.NET、エクスプローラー、シェル、COM) がユーザー モードで発生している場合、答えは、希望することを実行する方法がないということだと思います。
代わりに、おそらく別の方法があります。たとえば、シェル拡張機能にコードを追加して、プロセスが異常終了したかどうかを認識できるようにします。
あなたは、try / finally文(あなたがfinally節で解放のものを入れて)で、あなたのプロセス全体を包む試みることができるが、いくつかのケースでも、それは十分ではありません。
実は、私は、メインスレッドがまだできるようになります何かが子スレッドでうまくいかない場合のように、あなたのメインスレッドですべてのものとThread.Join()を行うには、あなたのプロセスから、バックグラウンドスレッドを起動することができると思います物事が権利を取得。全体のプロセスが何らかの理由で終了します場合はもちろん、これは動作しません。
また、子プロセスを起動し、Process.WaitForExitを(呼び出し)が、私は自分の殻に関連したものは、マルチプロセスアプローチで仕事ができるかはわからない可能性があります。