一尘不染

为什么关闭以AllocConsole启动的控制台会导致我的整个应用程序退出?我可以改变这种行为吗?

c#

我想发生的事情是控制台窗口刚刚消失,或者更好的是它已被隐藏,但是我希望我的应用程序继续运行。那可能吗?我希望能够使用Console.WriteLine并将控制台用作输出窗口。我希望能够隐藏和显示它,并且我不希望整个应用程序因控制台关闭而消失。

编辑

码:

internal class SomeClass {

    [DllImport("kernel32")]
    private static extern bool AllocConsole();

    private static void Main() {
        AllocConsole();
        while(true) continue;
    }
}

编辑2

根据此问题评论中的建议,我在此处[ Capture console exit
C#
]
尝试了可接受的解决方案。该示例代码存在bug,因为DLLImport需要为“ kernel32.dll”或“ kernel32”,而不是“
Kernel32”。进行更改后,单击控制台窗口上的X时,我会收到一条消息,通知我的处理程序CTRL_CLOSE_EVENT。但是,调用FreeConsole和/或返回true不会阻止应用程序终止。


阅读 817

收藏
2020-05-19

共1个答案

一尘不染

嗯,是的,这是使用Windows控制台子系统的警告之一。当用户关闭控制台窗口时(无论控制台如何分配), 所有附加到控制台的进程都将终止
。对于控制台应用程序(即,专门针对控制台子系统的应用程序,而不是标准Windows应用程序),这种行为是很有意义的,但是在像您这样的情况下,这可能是一个很大的麻烦。

我知道的唯一解决方法是使用SetConsoleCtrlHandlerfunction,它允许您为Ctrl+ CCtrl+
Break信号以及系统事件(例如用户关闭控制台窗口,用户注销或系统关闭)注册处理函数。。该文档说,如果您只想忽略这些事件,则可以传递null第一个参数。例如:

[DllImport("kernel32")]
static extern bool SetConsoleCtrlHandler(HandlerRoutine HandlerRoutine, bool Add);

delegate bool HandlerRoutine(uint dwControlType);

static void Main()
{
    AllocConsole();
    SetConsoleCtrlHandler(null, true);
    while (true) continue;
}

完美适用于Ctrl+ CCtrl+
Break信号(否则也会导致您的应用程序终止),但不适用于您要查询的信号CTRL_CLOSE_EVENT,即系统在用户关闭界面时生成的信号。控制台窗口。

老实说,我不知道如何防止这种情况。甚至SDK的示例实际上也不允许您忽略CTRL_CLOSE_EVENT。我在一个小型测试应用程序中进行了尝试,当您关闭窗口并打印消息时会
发出蜂鸣声 ,但是该过程仍然会终止。

也许更令人担忧的是,文档使我认为无法避免这种情况:

当用户关闭控制台,注销或关闭系统时,系统会生成CTRL_CLOSE_EVENTCTRL_LOGOFF_EVENTCTRL_SHUTDOWN_EVENT发出信号,以使进程有机会在终止之前进行清理。控制台功能或调用控制台功能的任何C运行时功能在处理上述三个信号中的任何一个期间可能无法可靠地工作。原因是在执行过程信号处理程序之前,可能已调用了部分或全部内部控制台清除例程。

那是我的最后一句话。如果控制台子系统响应于用户试图关闭窗口而 立即 开始自动清理,则事后可能无法将其停止。

(至少现在您了解了问题。也许其他人可以提出解决方案!)

2020-05-19