2013-05-21 8 views
6

atexit機能があり、通常のプロセス終了時に.NETコードが実行されますか? <code>C</code>で

のatexit()関数は、出口を介して、(3)またはプログラムのmain()からの戻りを介してのいずれかで、正常なプロセスの終了時に呼び出される所定の関数を登録します。

Pythonにも同様の機能があります。

.NETは、通常のプロセス終了時にコードを呼び出す方法を提供していますか?私はDomainUnloadProcessExitのようなものがあることを知っていますが、少なくとも私が知る限り、これらは信頼できません - アプリケーションはWindowsフォーム(またはWPFアプリケーション)か何かを必要とします。私は.dll用のコードを書いているので、メインプログラムの機能を捨てて、try/catchでラップするようなことには頼ることができません。

私の究極の目標は、ファイルのクリーンアップ(つまり、バッファをフラッシュして閉じる)です。管理されていないコードを呼び出すことができます。 win32apiフックや何か、私はそれで完璧にいいです。

+0

SetConsoleCtrlHandlerのCTRL_CLOSE_EVENTイベントを試すことができます。 http://msdn.microsoft.com/en-us/library/windows/desktop/ms686016%28v=vs.85%29.aspx –

答えて

6

私が知っている簡単な答えはありません。

あなたは堅牢なDLLを作成したい場合、あなたはいくつかのシナリオのために準備する必要があります

  1. あなたのコードは、デフォルトのAppDomainに、.NETアプリケーションでホストされています。 (簡単なシナリオ)
  2. コードは、.NETアプリケーション、ホストコードで作成されたAppDomainでホストされます。
  3. あなたのコードは、アンマネージドアプリケーション(CLRをホストする)でホストされています。

第3のシナリオは、ホストでCLRを無効にすることができ、管理されたコードはもう実行されないため、最も扱いにくいシナリオです。

System.Windows.Forms.Application.ApplicationExitは、WinFormアプリケーションにのみ適用されるため、悪いことです。

System.AppDomain.DomainUnloadそれ自体は、デフォルトのAppDomainのために生成されることはないので、それ自体では問題ありません。

AppDomain.ProcessExit単独でコードが別のAppDomainでホストされている場合、ホストはそのAppDomainをアンロードして、イベントが発生しないようにします。

私は、ほとんどのケースをカバーしようとしているようなもの使用して起動したい

if (AppDomain.CurrentDomain.IsDefaultAppDomain()) 
    AppDomain.CurrentDomain.ProcessExit += MyTerminationHandler; 
else 
    AppDomain.CurrentDomain.DomainUnload += MyTerminationHandler; 

をしかし、次の発言(from MSDN)に気づくの操作を行います。すべてのProcessExitイベントの総実行時間

をプロセスのシャットダウン時にすべてのファイナライザの合計実行時間が制限されているのと同じように、ハンドラは制限されています。デフォルトは2秒です。アンマネージホストは、OPL_ProcessExit列挙値を指定してICLRPolicyManager :: SetTimeoutメソッドを呼び出すことによって、この実行時間を変更できます。

上記のコードでは、3番目のシナリオは無人です。 (最初の2と一緒に)そのシナリオに対処するための私の知っている二つの方法

まず次のように、あなたは、System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanupメソッドを使用することができますがあります。

{ 
// this goes at your code's entry point 
    RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(MyExecutionCode, MyCleanupCode, null); 
} 
static void MyExecutionCode(object data) { /* your execution code here */} 
static void MyCleanupCode(object data, bool exceptionThrown) { /* your cleanup code here */ } 

第二に、あなたはSystem.Runtime.ConstrainedExecution.CriticalFinalizerObjectを利用することができますクラス(see MSDN here)を継承し、クリーンアップコードをファイナライザに入れます。これには、クリーンアップコードがConstrained Execution Regionガイドラインに準拠する必要があります。

+0

私は 'CriticalFinalizerObject'を使うか、 'Critical/SafeHandle'です。私は実際には今日これに遭遇しましたが、実装/テストする時間はありませんでしたが、私はそれが私が望むものを提供するべきだと考えています。 –

関連する問題