明确的代码,以防止交流#控制台应用程序从离开[直到自定义清理代码已完成](The definitiv

2019-09-22 18:19发布

我们可以一起拿出的东西,控制-C,控制通断工作,注销,窗口X按钮按下,等等?

这是我到目前为止有:

class Program
{  
    private static ConsoleEventHandlerDelegate consoleHandler;
    delegate bool ConsoleEventHandlerDelegate(CtrlTypes eventCode);

    static void Main(string[] args)
    {
        consoleHandler = new ConsoleEventHandlerDelegate(ConsoleCtrlCheck);
        SetConsoleCtrlHandler(consoleHandler, true);

        System.Diagnostics.Process.GetCurrentProcess().Exited 
           += delegate(object sender, EventArgs e) 
        {              
            GeneralManager.Stop();
        };

        Console.CancelKeyPress += delegate(object sender,
                                ConsoleCancelEventArgs e)
        {
            e.Cancel = false;
            GeneralManager.Stop();
        };

        GeneralManager.Start();
    }

    private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
    {
        switch (ctrlType)
        {                
            case CtrlTypes.CTRL_C_EVENT:

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

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

            case CtrlTypes.CTRL_CLOSE_EVENT:

                Console.WriteLine("Program being closed!");
                GeneralManager.Stop();
                break;

            case CtrlTypes.CTRL_LOGOFF_EVENT:
            case CtrlTypes.CTRL_SHUTDOWN_EVENT:

                Console.WriteLine("User is logging off!");
                GeneralManager.Stop();
                break;                           
        }
        return true;
    }

    #region unmanaged

            [DllImport("kernel32.dll")]
          static extern bool SetConsoleCtrlHandler(ConsoleEventHandlerDelegate
            handlerProc, bool add);

    public delegate bool HandlerRoutine(CtrlTypes CtrlType);

    public enum CtrlTypes
    {
        CTRL_C_EVENT = 0,
        CTRL_BREAK_EVENT,
        CTRL_CLOSE_EVENT,
        CTRL_LOGOFF_EVENT = 5,
        CTRL_SHUTDOWN_EVENT
    }

    #endregion
}

两个问题:

  1. 在管理控制,中断处理程序,如果我们设置e.Cancel = true失败与.NET4例外。 这是MSDN文章没有工作,围绕指出: http://msdn.microsoft.com/en-us/library/system.consolecanceleventargs.cancel.aspx

  2. 我不知道如何取消在关闭ConsoleCtrlCheck 。 我得到一两秒钟做一些清理工作,但我宁愿取消,并确保这一切又得当。

更新:

感谢您的答复。 这两个Upvoted。 会等待,看是否有人能拿出直接解决了我问一个答复,否则将接受“使用NT服务”的答案之一。

Answer 1:

我还没有尝试做这种事情有一个控制台应用程序,但你可以做一个Windows窗体(或WCF应用程序)更好。 他们会给你一个FormClosing事件是撤销。 或者,使用Windows服务,如果你正在编写一个网络服务,它提供了一个界面干净停止你的应用程序。

如果你真的热衷于一个控制台应用程序,也许是一个try {} finally {}周围所有的代码条款或一些更奇特的像一个关键finaliser可以允许您运行清理代码。 但这真的不适合工作的正确的工具。

而且有你不能阻止你的应用程序被关闭的情况下,例如:电源故障,或任务管理器kill命令(如果一个应用程序通过X没有关闭,任务管理器是我想达到的第一个工具)。

因此,编写你的服务应用,使得所有客户端请求被记录到一个事务日志(如SQL服务器一样)。 如果您意外(通过任何情况下),任何事情已经发生了中断,直到这一点是在日志中。 当在下一个开始你的服务,重播日志。

你的一个事情,日志将被“我是在一次关机干净T ”。 如果重新启动,并没有发现在你的日志的结尾该项目,你就知道出事了,你可以采取任何行动是必需的。

如果你需要知道你的服务是干什么的,使用很多的一个日志 框架来管事件的第二应用程序,这只是显示活动。



Answer 2:

我需要等待挂起的用户请求来完成的,干净断开它们,在数据库上运行几个查询,以反映状态变化(S)等。 这是一个TCP服务器。

这时不要运行它作为一个控制台或任何其他类型的客户端应用程序的。

只要运行它作为Windows(NT)服务,你就不用担心是功率损耗和停止信号的唯一事件。

使用UPS,并确保你能在合理的时间跨度关闭。



Answer 3:

我花了几个小时看着这个和我没有现在的时间来建立一个工作代码; 因为虽然它可能很短,得到它的权利将需要一段时间。 我只是给你链接到真实需要得到这个工作的各种东西:

http://pastebin.com/EzX3ezrf

从粘贴代码总结的经验教训:

  1. 需要一个消息泵来处理一些/所有WM_QUERYENDSESSION,WM_ENDSESSION,CTRL_SHUTDOWN_EVENT的(在C#SystemEvents.SessionEnding可以覆盖一些/所有这些)

  2. 得到一个消息泵最简单的方法是让一个隐藏的表单/窗口的应用程序,但我记得很可能建立一个控制台应用程序,并添加消息泵也。 我并没有包括在粘贴代码虽然。

  3. “如果一个应用程序必须阻止潜在的系统关机,它可以调用ShutdownBlockReasonCreate功能”

  4. 作为AllocConsole用于创建控制台,您需要使用SetConsoleCtrlHandler并在处理程序使用了ExitThread(1)。 这是一个“黑客”是杀死了,否则将关闭控制台线程。 它在FarManager使用。 例如参见interf.cpp

  5. 你需要使用AllocConsole时也初始化和清理控制台。

  6. 按CTRL + C报告给弄乱输入。 我不知道如果FarManager是处理这种情况。 有在interf.cpp的CTRL_BREAK_EVENT处理程序,我不知道它做什么一些代码。

  7. FarManager也处理WM_POWERBROADCAST,可能与暂停办

如果一切是不够的(应该是),你也可以添加控制台到另一个进程和IPC邮件给它喜欢在这里显示。 为什么关闭该开始用AllocConsole引起了我的整个应用程序退出控制台? 我可以改变这种行为?

RMTool可以用来模拟注销/关机信息来进行测试: http://download.microsoft.com/download/d/2/5/d2522ce4-a441-459d-8302-be8f3321823c/LogoToolsv1.0.msi

MSDN有一些C#代码也在microsoft.win32.systemevents.sessionending.aspx和microsoft.win32.systemevents.aspx(隐藏表单示例)

该mischel.com/pubs/consoledotnet/consoledotnet.zip有正在使用AllocConsole样本winTest项目和一些事件的处理。



文章来源: The definitive code that prevents a c# console app from exiting [until custom cleanup code has completed]