2009-05-08 41 views
9

Windowsアプリケーションのタスクマネージャ終了プロセスを同じWindowsアプリケーション内でキャプチャすることは可能ですか?私はC#2.0のWinアプリケーションを使用しています。終了処理が行われると、データベース処理(DB内のフラグを 'Y'から 'N'に変更)したいと考えています。Windowsアプリケーションの処理終了処理

答えて

10

いいえ、プロセスを終了するためのオペレーティングシステムの決定にフックすることはできません。これはタスクマネージャーでは行われないことに注意してください。プロセスの終了はカーネルの責任です。

あなたはここに2つのことを行う必要があります:終了するには、アプリケーションを伝える通常のユーザ・インタフェース・メッセージに

  1. 接続イベントハンドラを。これらのイベントを使用してデータを永続化したり、リソースを解放したり、正常に終了することができます。
  2. エラーをキャッチし、可能であればデータをクリーンアップして保存するのに適切な例外を処理します。

ここには、あなたが求めていることができない理由を説明するRaymondのブログへの3つのリンクがあります。

また、私は同様のStackOverflowの質問hereを取り上げました。

+0

はい、私はイベント処理を行うことができます。しかし、ユーザーがタスクマネージャーから終了プロセスを実行した場合、彼は依然としてデータベースに「ログイン」してフラグが立てられ、再度ログインしようとすると、彼は許可されません。 最後のプロセスメッセージで「保存されていないデータを保存できないなど」というメッセージが表示されます –

+0

これは設計によるものですが、WindowsがアプリケーションにTerminateProcess()タスクスケジューラは、プロセスを正常終了させるために設計されたものではありません。つまり、プロセスを終了させるのではなく、プロセスを終了させることを意図しています。 あなたの意図は貴族です!データを確実に永続化しますが、ユーザーがプロセスを停止させたい場合は、TerminateProcess()を実行してください。 – Foredecker

+0

Rashmi P.のように、ツリーからフォレストが見えません。新しいプロセスで新しい接続が作成され、問題は発生しません- – GregC

1

あなたができることは、プロセスIDを取得してプロセスを監視し、HasExitedプロパティを使用してプロセスが終了しているかどうかを確認することです。以下は、迅速なVBのコードは、プロセスが終了しているかどうかのInternetExplorerやボタンのチェックを開始し

Public Class Form1 
    Dim p As ProcessStartInfo 
    Dim process As Process 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
     p = New ProcessStartInfo("iexplore.exe") 
     process = process.Start(p) 
    End Sub 

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 
     MsgBox(process.Id) 
     If process.HasExited Then 
      MsgBox("yes") 
     Else 
      MsgBox("no") 
     End If 
    End Sub 
End Class 

コードの上に(私はこれは別のフォーラムで私が書いた。今、VSを持っていけないすみません)です。同様のプロセスを使用して、実行中のすべてのプロセスを取得し、processIDを使用することができます。

+0

Shobanねえ、私は使用して外部アプリ終了処理(iexploremメモ帳など)をキャプチャすることができますあなたのコード。しかし、私は同じアプリケーション(上記のurコードでForm1が含まれています) –

+0

の最後のタスクをキャプチャするために何をする必要があります彼は、 "同じWindowsアプリケーション自体の中で"と述べた。 –

+1

同じアプリではできませんので、Shobanのアイデアはできるだけ近くにあります。 – RichieHindle

1

これはアプリケーション内から行うことはできません。終了タスクの目的は、プロセスを直ちに停止することです。これはクリーンアップコードの実行を許可しません。

あなたの目標を達成するためにショーバンは別の方法を指摘しました。別のアプリケーションまたはサービスでは、メインプロセスを探す必要があります。他のプロセスがメインプロセスを見つけることができない場合は、その時点でデータベース処理を実行できます。

3

少し異なるアプローチはどうですか:

アプリケーションで日付の時刻フィールドを更新しましたか? LastPollDateは実行中に非常に頻繁に使用され、別のフィールドがあります。 "AppTerminatedNormally"をNに設定し、フォーム終了イベントを受け取った場合はYに変更します。

タスクマネージャーを使用してアプリが強制終了された場合、日付はもう更新されず、AppTerminatedNormallyは引き続きnoです。

LastPollDateが10分より古いすべての行を検索し、AppTerminatedNormallyがNであり、異常終了したすべてのセッションを持つクエリを実行することができます。

+0

これは良い方法です。ありがとう – Sakthivel

2

あなたはすべてこの記事で吐き出すつもりですが、ここには...

不適切なレベルで問題を解決しようとしています(カーネルがアプリを強制終了しているときなど)。実際の問題は、データベースがクライアントアプリケーションの存在(または不在)を正しく反映していることを保証することです。

これを解決するには、アプリケーションがユーザーのやりとりの間に「不適合状態」になるのを避けます。つまり、すぐにコミットできないトランザクションを開始しないでください。半分書込みまたは読めない状態でファイルを残すファイルにデータを書き込まず、アプリケーションの外部にリソースが不当に保持されないようにしてくださいユーザインタラクションの外部にある状態。別の言い方をすれば、あなたのアプリがイベントハンドラに応答していない場合、すぐに閉じる準備ができているはずです。

上記の手順を実行すると、終了する前に「すばやくクリーンアップ」する必要があるシナリオはほとんどありません。ユーザが「OK」または「保存」をクリックするなどの対話の外では、よく書かれたアプリケーションは、データストアの永続的な損傷または破損なしに即座に終了することができます。

あなたは絶対に(ユーザーがログインしているかどうかを検出するのに使用されるパターンの典型的な音)終了時にデータベースにフラグを設定する必要がある場合は、次の選択肢のいずれかを考慮してください。

  1. 定期的に(おそらく30秒ごとに1回)、データベースのタイムスタンプのようなフィールドを挿入/更新し、アプリケーションがどのくらい最近オンラインになったかを示します。他のアプリケーションは、これらのタイムスタンプを調べて、別のアプリケーションがどのくらい最近オンラインになったかを判断できます。値が過去30秒以内であれば、他のアプリはまだopnlineです。

  2. Woodhengeが正しく示唆しているように、メインアプリケーションのステータスを監視するために、別個のプロセス(理想的にはサービス)を作成してください。 Windowsサービスは、サービスが失敗した場合に自動的に再起動するように設定できます。この監視プロセスは、データベースにタイムスタンプを発行します。これまで「不適合状態」のデータベースを残すことなく、上記の提案の両方が本当の問題を解決する

通知は、アプリケーションがある場合(前述のフラグが「Y」である(アプリケーションがデータベースにアクセスしているか否かを検出します)実際に死んで、フラグは "N"でなければなりません)。

2

は、Windows Vistaの(またはそれ以上)をターゲットにしている場合は、RegisterApplicationRecoveryCallbackのAPIに興味があるかもしれない...

http://msdn.microsoft.com/en-us/library/aa373345.aspx

それが呼び出されます、あなたのアプリでコールバック・ルーチンを指定することができますプロセスがクラッシュする直前。 N.B.クラッシュのためだけであり、プロセスが故意に殺された場合は自動的に呼び出されません。

C#からこのAPIにp/invokeすることはできますが、コールバックが呼び出されたときにアプリが既に非常に悪い状態にあり、そのことに関するごくわずかな仮定をすることができますあなたの記憶の状態。このルーチンで使用したいメモリ内のデータがある場合は、非常に一般的なスコープで静的にデータを入れて、コールバックルーチンが正しく整理されていない可能性が最も高くなるようにします走る

など、あなたが自動的に障害が発生した後にアプリを再起動することができ、この1に関連するいくつかの他の興味深いのAPIは、ありますが、

+0

こんにちは、マーティンに感謝...私はこの1つを見てみましょう:) –

関連する問題