为什么关闭使用 AllocConsole 启动的控制台会导致我的整个应用程序退出?我可以改变这种行为吗? [英] Why does closing a console that was started with AllocConsole cause my whole application to exit? Can I change this behavior?

查看:60
本文介绍了为什么关闭使用 AllocConsole 启动的控制台会导致我的整个应用程序退出?我可以改变这种行为吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

What I want to have happen is that the console window just goes away, or better yet that it is hidden, but I want my application to keep running. Is that possible? I want to be able to use Console.WriteLine and have the console serve as an output window. I want to be able to hide and show it, and I don't want the whole app to die just because the console was closed.

编辑

代码:

internal class SomeClass {

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

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

编辑 2

我在这里尝试了接受的解决方案 [捕获控制台退出 C#],根据关于这个问题的评论中的建议.示例代码存在错误,因为 DLLImport 需要是kernel32.dll"或kernel32",而不是Kernel32".进行该更改后,当我单击控制台窗口上的 X 时,我会收到一条消息给我的 CTRL_CLOSE_EVENT 处理程序.但是,调用 FreeConsole 和/或返回 true 不会阻止应用程序终止.

I tried the accepted solution here [ Capture console exit C# ], per the suggestion in the comments on this question. The example code is bugged in that the DLLImport needs to be "kernel32.dll" or "kernel32", not "Kernel32". After making that change, I'm getting a message to my handler for CTRL_CLOSE_EVENT when I click the X on the console window. However, calling FreeConsole and/or returning true doesn't prevent the application from terminating.

推荐答案

啊,是的,这是使用 Windows 控制台子系统的注意事项之一.当用户关闭控制台窗口时(不管控制台是如何分配的),连接到控制台的所有进程都将终止.这种行为对于控制台应用程序(即专门针对控制台子系统的应用程序,而不是标准的 Windows 应用程序)来说显然是有意义的,但在像您这样的情况下,它可能是一个主要的痛苦.

Ah, yes, this is one of the caveats of using the Windows console subsystem. When the user closes the console window (regardless of how the console was allocated), all of the processes that are attached to the console are terminated. That behavior makes obvious sense for console applications (i.e., those that specifically target the console subsystem, as opposed to standard Windows applications), but it can be a major pain in cases like yours.

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

The only workaround that I know of is to use the SetConsoleCtrlHandler function, which allows you to register a handler function for Ctrl+C and Ctrl+Break signals, as well as system events like the user closing the console window, the user logging off, or the system shutting down. The documentation says that if you're only interested in ignoring these events, you can pass null for the first argument. For example:

[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.

That works perfectly for Ctrl+C and Ctrl+Break signals (which would have otherwise caused your application to terminate as well), but it doesn't work for the one you're asking about, which is the CTRL_CLOSE_EVENT, generated by the system when the user closes the console window.

老实说,我不知道如何防止这种情况发生.即使 SDK 中的示例 实际上也不允许你忽略 CTRL_CLOSE_EVENT.我在一个小测试应用程序中尝试过,当您关闭窗口并打印消息时它发出哔哔声,但进程仍然终止.

Honestly, I don't know how to prevent that. Even the sample in the SDK doesn't actually allow you to ignore the CTRL_CLOSE_EVENT. I tried it in a little test app, and it beeps when you close the window and prints the message, but the process still gets terminated.

也许更令人担忧的是,文档让我认为无法防止这种情况发生:

Perhaps more worryingly, the documentation makes me think it is not possible to prevent this:

当用户关闭控制台、注销或关闭系统时,系统会生成 CTRL_CLOSE_EVENTCTRL_LOGOFF_EVENTCTRL_SHUTDOWN_EVENT 信号,以便该过程有机会在终止之前进行清理.控制台函数,或调用控制台函数的任何 C 运行时函数,在处理前面提到的三个信号中的任何一个时,可能无法可靠地工作.原因是在执行进程信号处理程序之前,可能已经调用了部分或全部内部控制台清理例程.

The system generates CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT signals when the user closes the console, logs off, or shuts down the system so that the process has an opportunity to clean up before termination. Console functions, or any C run-time functions that call console functions, may not work reliably during processing of any of the three signals mentioned previously. The reason is that some or all of the internal console cleanup routines may have been called before executing the process signal handler.

最后一句话吸引了我的眼球.如果控制台子系统在自己立即开始清理以响应用户尝试关闭窗口,则可能无法在事后停止它.

It's that last sentence that catches my eye. If the console subsystem starts cleaning up after itself immediately in response to the user attempting to close the window, it may not be possible to halt it after the fact.

(至少现在你明白了这个问题.也许其他人可以提出解决方案!)

(At least now you understand the problem. Maybe someone else can come along with a solution!)

这篇关于为什么关闭使用 AllocConsole 启动的控制台会导致我的整个应用程序退出?我可以改变这种行为吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆