如何避免强制终止以停止控制台应用程序?

问题描述 投票:0回答:1

我需要能够按需优雅地关闭控制台应用程序。

使用这个post我能够在收到CTRL事件时控制退出。然而,我无法使用taskkill按需停止应用程序。

如果我尝试命令:

taskkill /im myapp

它响应:

错误:无法终止带有PID 23296的进程“MyApp.exe”。原因:此过程只能强制终止(使用/ F选项)。

c# windows console-application kill-process
1个回答
0
投票

基于添加到这篇文章的许多贡献以及detecting-console-application-exit-in-c我构建了以下帮助器,以优雅地停止taskkill信号上的控制台应用程序,但也停止任何其他关闭控制信号:

public class StopController : Form, IMessageFilter
{
    //logger
    private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    static private CancellationTokenSource cancellationTokenSource;

    public StopController(CancellationTokenSource cancellationTokenSource)
    {
        StopController.cancellationTokenSource = cancellationTokenSource;
        System.Windows.Forms.Application.AddMessageFilter(this);
        SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        this.WindowState = FormWindowState.Minimized;
        this.ShowInTaskbar = false;
    }
    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == 16)
        {
            log.Warn("Receiveing WF_Close event. Cancel was fired.");
            cancellationTokenSource.Cancel();
        }

        return true;
    }

    public static void Activate(CancellationTokenSource cancellationTokenSource)
    {            
        Task.Run(() => Application.Run(new StopController(cancellationTokenSource)));
    }
    #region unmanaged

    //must be static.
    private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
    {
        // Put your own handler here
        switch (ctrlType)
        {
            case CtrlTypes.CTRL_C_EVENT:

                log.Warn("CTRL+C received!. Cancel was fired.");
                cancellationTokenSource.Cancel();
                break;

            case CtrlTypes.CTRL_BREAK_EVENT:

                log.Warn("CTRL+BREAK received!. Cancel was fired.");
                cancellationTokenSource.Cancel();
                break;

            case CtrlTypes.CTRL_CLOSE_EVENT:

                log.Warn("Program being closed!. Cancel was fired.");
                cancellationTokenSource.Cancel();
                break;

            case CtrlTypes.CTRL_LOGOFF_EVENT:
            case CtrlTypes.CTRL_SHUTDOWN_EVENT:
                log.Warn("User is logging off!. Cancel was fired.");
                cancellationTokenSource.Cancel();
                break;

            default:
                log.Warn($"unknow type {ctrlType}");
                break;
        }
        return true;

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

用法:

  StopController.Activate(cancellationTokenSource);

无需更改为Windows应用程序。

© www.soinside.com 2019 - 2024. All rights reserved.