控制台,ctrl + c vs关闭按钮单击

时间:2016-03-09 15:39:25

标签: c# windows windows-7

当我在控制台窗口中单击ctrl + c时,会引发事件并且应用程序可以执行一些应该在退出之前执行的代码。

然而,当我点击[X]关闭按钮时,事件也会被提升,但是在很短的时间内,我的应用程序被强行关闭 - 当'结束执行'事件仍在进行中时。

是否可以在Windows强制关闭app之前设置更长的超时?

编辑:

我设置:

  [DllImport("Kernel32.dll")]
  static extern bool SetConsoleCtrlHandler(ControlEventHandler e, bool add);

  public delegate void ControlEventHandler(ConsoleEvent consoleEvent);

当我在控制台窗口上单击ctrl + c时,我收到:CTRL_C,我可以在mu事件处理程序中处理代码。

当我点击[x]关闭按钮时,我收到CTRL_CLOSE标志,我也可以处理处理程序,但仅限1-2秒。然后控制台windwo disappers ...

1 个答案:

答案 0 :(得分:1)

  

是否可以在Windows强制关闭app之前设置更长的超时?

不幸的是,没有。从Windows Vista开始,在控制台窗口自动关闭之前收到CTRL_CLOSE_EVENT后,只允许10秒左右的宽限期。如果您在10秒后没有退出处理程序,那么您的进程将被毫不客气地终止。 (显然,如果你早点从处理程序返回,你将不会得到整整10秒。)

据我所知,这是更大的设计策略的一部分,以确保应用程序无法覆盖用户的意愿。 Older versions of the SDK documentation提到了一个对话框,如果进程在某个超时期限内没有响应,则会出现一个对话框,但所有提到的内容都来自current version of the SDK documentation。对话框在Vista中进入MIA,它不再存在。这可能与应用程序无法再阻止系统关闭这一事实有关。

这不会影响您按 Ctrl + C ,因为这会产生不同的信号 - CTRL_C_EVENT。与 Ctrl + Break 相同,它会引发CTRL_BREAK_EVENT。但据我在文档中可以看出,CTRL_CLOSE_EVENTCTRL_LOGOFF_EVENTCTRL_SHUTDOWN_EVENT只是通知,让您有机会在文档之前进行清理终止。无法阻止终止或延长宽限期。

我只能想到一种解决方法,那就是禁用控制台窗口本身的关闭按钮。我看到你正在使用C#,因此需要一些P / Invoke:

[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();

[DllImport("user32.dll")]
static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

[DllImport("user32.dll")]
static extern bool DeleteMenu(IntPtr hMenu, uint uPosition, uint uFlags);

private const uint MF_BYCOMMAND = 0x0;
private const uint SC_CLOSE     = 0xF060;

void DisableConsoleCloseButton()
{
    IntPtr hWnd = GetConsoleWindow();
    if (hWnd != IntPtr.Zero)
    {
        IntPtr hMenu = GetSystemMenu(hWnd, false);
        if (hMenu != IntPtr.Zero)
        {
            DeleteMenu(hMenu, SC_CLOSE, MF_BYCOMMAND);
        }
    }
}

如果你走这条路,你显然需要为用户提供一些从应用程序中关闭控制台窗口的方法。在Win32-land中,该功能会调用FreeConsole函数来关闭它,但我敢打赌它包含在一个.NET类中。我太久了,不记得它叫什么。