4

我正在尝试,但到目前为止我发现的一切似乎都以 GUI 和表单应用程序为中心。那不是我正在使用的。

最终它将成为一项服务,但在完成之前我将它作为一个普通应用程序运行,问题是如果我只是不小心关闭它,它会使另一个服务挂起长达 30 分钟,并出现错误数据. 我虽然很容易添加一个监听器来捕捉正在关闭的应用程序。

但我就是想不通。

4

4 回答 4

5

在这里,您有一个完美的解决方案来满足您的需求:

在 C# 中检测控制台应用程序退出

该代码检测将关闭应用程序的所有可能事件:

  • 控制+C
  • 控制+中断
  • 关闭事件(程序的“正常”关闭,带有关闭按钮)
  • 注销事件(使用注销)
  • 关机事件(系统关闭)
namespace Detect_Console_Application_Exit2
{
  class Program
  {
    private static bool isclosing = false;

    static void Main(string[] args)
    {
      SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);
      Console.WriteLine("CTRL+C,CTRL+BREAK or suppress the application to exit");
      while (!isclosing) ;
    }

    private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
    {
      // Put your own handler here
      switch (ctrlType)
      {
        case CtrlTypes.CTRL_C_EVENT:
          isclosing = true;
          Console.WriteLine("CTRL+C received!");
          break;

        case CtrlTypes.CTRL_BREAK_EVENT:
          isclosing = true;
          Console.WriteLine("CTRL+BREAK received!");
          break;

        case CtrlTypes.CTRL_CLOSE_EVENT:
          isclosing = true;
          Console.WriteLine("Program being closed!");
          break;

        case CtrlTypes.CTRL_LOGOFF_EVENT:
        case CtrlTypes.CTRL_SHUTDOWN_EVENT:
          isclosing = true;
          Console.WriteLine("User is logging off!");
          break;
      }
      return true;
    }

    #region unmanaged

    // Declare the SetConsoleCtrlHandler function
    // as external and receiving a delegate.
    [DllImport("Kernel32")]
    public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);

    // A delegate type to be used as the handler routine
    // for SetConsoleCtrlHandler.
    public delegate bool HandlerRoutine(CtrlTypes CtrlType);

    // An enumerated type for the control messages
    // sent to the handler routine.
    public enum CtrlTypes
    {
      CTRL_C_EVENT = 0,
      CTRL_BREAK_EVENT,
      CTRL_CLOSE_EVENT,
      CTRL_LOGOFF_EVENT = 5,
      CTRL_SHUTDOWN_EVENT
    }

    #endregion

    }
}
于 2012-05-16T15:12:56.127 回答
2

尝试这个:

[编辑] 这是上面发布的链接的修改版本。

注意:如果用户单击红色 X 关闭控制台窗口,在您的应用程序被终止之前,您的响应时间非常有限!如果您运行以下程序,请查看消息框在消失之前显示了多长时间。

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;


namespace Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            SetConsoleCtrlHandler(ConsoleCtrlCheck, true);
            Console.WriteLine("CTRL+C,CTRL+BREAK or suppress the application to exit");

            while (!isclosing)
            {
                Thread.Sleep(1000);
            }
        }

        private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
        {
            // Put your own handling here:

            switch (ctrlType)
            {
                case CtrlTypes.CTRL_C_EVENT:

                    isclosing = true;

                    Console.WriteLine("CTRL+C received!");

                    break;

                case CtrlTypes.CTRL_BREAK_EVENT:

                    isclosing = true;

                    Console.WriteLine("CTRL+BREAK received!");

                    break;

                case CtrlTypes.CTRL_CLOSE_EVENT:

                    isclosing = true;

                    Console.WriteLine("Program being closed!");
                    MessageBox.Show("AHA!");

                    break;

                case CtrlTypes.CTRL_LOGOFF_EVENT:
                case CtrlTypes.CTRL_SHUTDOWN_EVENT:

                    isclosing = true;

                    Console.WriteLine("User is logging off!");

                    break;
            }

            return true;
        }

        #region unmanaged

        // Declare the SetConsoleCtrlHandler function as external and receiving a delegate.

        [DllImport("Kernel32")]

        public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);

        // A delegate type to be used as the handler routine for SetConsoleCtrlHandler.

        public delegate bool HandlerRoutine(CtrlTypes CtrlType);

        // An enumerated type for the control messages sent to the handler routine.

        public enum CtrlTypes
        {

            CTRL_C_EVENT = 0,
            CTRL_BREAK_EVENT,
            CTRL_CLOSE_EVENT,
            CTRL_LOGOFF_EVENT = 5,
            CTRL_SHUTDOWN_EVENT
        }

        #endregion

        private static bool isclosing;
    }
}
于 2012-05-16T15:16:08.747 回答
1

如果要在应用程序内部处理事件,

  1. 如果是windows服务,

    可以使用ServiceBase.OnStop

  2. 如果是 WCF 服务 ,可以使用ServiceHost.Closed事件。ServiceHost 从 Communication Host 继承 Closed(和相关事件)

如果要在单独的应用程序中处理事件,可以使用Process.Exited事件。

var serviceProcesses = Process.GetProcessesByName("service.exe");
if(serviceProcesses != null && serviceProcesses.Length>0)
{
    serviceProcesses[0].Exited += OnServiceClosed;
}
于 2012-05-16T15:18:34.203 回答
0

AppDomain.CurrentDomain.ProcessExit事件?

于 2012-05-16T15:15:02.113 回答