none
外部プロセスの終了要求をコンソールアプリで検知するには? RRS feed

  • 質問

  • VS2017をコンソールアプリケーションを作成しています。

    外部アプリケーションから終了要求が行われたことを検知したいでのですが

    受け取れずに強制終了しています。

    終了方法はC++からtaskkillを使用しています。

    終了させられる側が終了要求が来たことを検知する方法はありませんか?

    宜しくお願い致します。

    2018年8月7日 10:26

回答

  • taskkill でプロセスが強制終了される場合、強制終了される側のプロセスで終了要求を検出することはできないと思います。

    参考
    https://teratail.com/questions/87709

    強制終了する側のアプリがご自身作成のアプリの場合は、taskkillを使う前に、終了の信号を送る方法(GenerateConsoleCtrlEvent関数、SetConsoleCtrlHandler関数等)は使えないでしょうか。

    参考
    https://msdn.microsoft.com/ja-jp/library/cc429733.aspx

    2018年8月7日 10:53
  • taskkillは/fオプションを付けない場合、対象のプロセスに対してWM_QUITメッセージを送信し、メッセージループを終了させます。

    一般的なコンソールアプリの場合メッセージループを持っていないので、WM_QUITも受け取れず終了しません。

    コンソールアプリでも、ワーカースレッドでメインの処理を動かしておき、メインスレッドではSystem.Windows.Forms.Application.Runさせておけば、Application.Runから復帰することでtaskkill(/fなし)を検知できます。(System.Windows.Forms.dllの参照追加が必要)

    • 回答としてマーク yokohamaUser 2018年8月8日 0:48
    2018年8月8日 0:29

すべての返信

  • taskkill でプロセスが強制終了される場合、強制終了される側のプロセスで終了要求を検出することはできないと思います。

    参考
    https://teratail.com/questions/87709

    強制終了する側のアプリがご自身作成のアプリの場合は、taskkillを使う前に、終了の信号を送る方法(GenerateConsoleCtrlEvent関数、SetConsoleCtrlHandler関数等)は使えないでしょうか。

    参考
    https://msdn.microsoft.com/ja-jp/library/cc429733.aspx

    2018年8月7日 10:53
  • ご回答ありがとうございます。

    呼出し元のアプリは私の担当ではないので相談してみますが、複数のアプリを同時に幾つも起動している為、taskkillをできれば使用したいです。

    その担当者がいうには「taskkillの通常終了では終わらなくて、パラメータに強制終了があったのでそれを使って終了させた」そうです。と、すると強制終了ではない通常の終了があるのかと考えた次第です。

    通常終了で終わらなかったというのは、私のプログラムはTCPのソケットを使用しているので、待ちの時に終了シグナルがきたのではと考えております。

    2018年8月8日 0:18
  • taskkillは/fオプションを付けない場合、対象のプロセスに対してWM_QUITメッセージを送信し、メッセージループを終了させます。

    一般的なコンソールアプリの場合メッセージループを持っていないので、WM_QUITも受け取れず終了しません。

    コンソールアプリでも、ワーカースレッドでメインの処理を動かしておき、メインスレッドではSystem.Windows.Forms.Application.Runさせておけば、Application.Runから復帰することでtaskkill(/fなし)を検知できます。(System.Windows.Forms.dllの参照追加が必要)

    • 回答としてマーク yokohamaUser 2018年8月8日 0:48
    2018年8月8日 0:29
  • ありがとうございます。

    >一般的なコンソールアプリの場合メッセージループを持っていないので、WM_QUITも受け取れず終了しません。

    なるほど、納得しました。提示して頂いた方法で作成仕直します。

    改めてありがとうございました。

    2018年8月8日 0:51
  • 追記。

    先のレスで述べたような構成にする場合、エントリポイントであるMainメソッドには [STAThread] 属性を付けた方が良いです。

    また、taskkillによらずプロセス内でApplication.Runを終了させるには、Application.Exitを使用します。

    2018年8月8日 0:57
  • 外部プロセスから任意の他のプロセスを落とす方法は色々ありますが、taskkill などの「お行儀の良い」方法で落とされることを前提とするなら、原理的には可能です。
    taskkill でプロセスが落とされる場合、その落とされる対象となるプロセス側では、最終的に ntdll!RtlExitUserProcess コールが発生します。
    つまり、自プロセス内の ntdll!RtlExitUserProcess ルーチンにフックを仕掛けておけば可能です。
    (ただし API Hook を実現するには、それなりのスキルが必要になります。)

    2018年8月8日 2:29
  • ありがとうございます。taskkillでも(/fなし)お教えいただいた

    SetConsoleCtrlHandler

    が使えました。ありがとうございます。

    2018年8月8日 6:00