C# 如何在命令行应用程序中接收系统关闭或退出事件



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

最终它将是一项服务,但在完成之前,我将它作为普通应用程序运行,问题是如果我意外关闭它,它会让另一个服务挂起长达 30 分钟,并带有不良数据。我虽然很容易添加一个侦听器来捕获正在关闭的应用程序。

但我就是想不通。

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

在 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
    }
}

试试这个:

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

注意:如果用户单击红色 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;
    }
}

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

  1. 如果是视窗服务,

    可以使用ServiceBase.OnStop

  2. 如果是 WCF 服务可以使用 ServiceHost.Closed 事件。服务主机从通信主机继承已关闭(和相关事件)

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

var serviceProcesses = Process.GetProcessesByName("service.exe");
if(serviceProcesses != null && serviceProcesses.Length>0)
{
    serviceProcesses[0].Exited += OnServiceClosed;
}

AppDomain.CurrentDomain.ProcessExit事件?

最新更新