2

I needed to be able to output to a console from my GUI-based app written in C++, so I chose to use the AttachConsole(ATTACH_PARENT_PROCESS) API and this code to do so. That method works great, except that when I start my GUI app from a command prompt window the GUI app starts just fine but when I close the command prompt window my GUI app is terminated (note, not closed, but terminated.) Is there any way to prevent this app termination?

ahmd0
  • 16,633
  • 33
  • 137
  • 233
  • Why don't you use `AllocConsole` instead. That would appear to be more suitable to your needs. GUI and console apps don't typically mix very well. – David Heffernan Feb 20 '13 at 21:33
  • I don't call `AllocConsole` because I don't need a console allocated if the GUI app is run by itself (like you would normally run it.) With that API the command prompt window opens up beside my GUI app. – ahmd0 Feb 20 '13 at 21:36
  • @Cheersandhth.-Alf: I'm sorry, I'm not familiar with `cat`? Can you give more details? – ahmd0 Feb 20 '13 at 21:37
  • @Cheersandhth.-Alf `type` would the Windows analog of `cat` – shf301 Feb 20 '13 at 21:47
  • 1
    As I understand it, when the console is closed, if your process is attached to it, your process will die. And there's no way to avoid that. http://stackoverflow.com/questions/11959643/why-does-closing-a-console-that-was-started-with-allocconsole-cause-my-whole-app – David Heffernan Feb 20 '13 at 21:57
  • @DavidHeffernan: Thanks. This is technically a duplicate. Otherwise your comment is the answer (not the one I was hoping for though.) – ahmd0 Feb 20 '13 at 22:09

2 Answers2

1

You can prevent your application from closing when somebody closes the console window.

It involves calling SetConsoleCtrlHandler to set a HandlerRoutine that intercepts those events.

If you want the console window to close, but leave your app running, you might be able to call FreeConsole in your HandlerRoutine. If that doesn't work, then handle the message to prevent the console window from being destroyed, and set a flag or a timer that will cause your app to call FreeConsole after returning from the handler.

As I recall, you can't prevent the window from closing when the user hits the X on the window. What I did to prevent that is modify the window menu. See http://blog.mischel.com/2008/07/14/going-too-far-back/ for some details.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
  • Thanks. I tried it. Unfortunately when I call `FreeConsole` from the handler my GUI app gets terminated anyway. And disabling the close button is way too extreme for my linking. What I was thinking is to attach the console to my GUI process only for the moment when printf() or any other text output is done, and then detach it right after. This way it won't stay attached. What I can't seem to figure out is how to gracefully detach it. Any ideas? – ahmd0 Feb 21 '13 at 05:36
  • Doesn't `FreeConsole` detach gracefully? – Jim Mischel Feb 21 '13 at 06:32
  • This is all covered in the Q which I linked to in comments to this Q. – David Heffernan Feb 21 '13 at 07:08
  • @DavidHeffernan: Yes, you're right. I didn't read your comment until after I'd posted. My bad. – Jim Mischel Feb 21 '13 at 13:21
  • @JimMischel: No `FreeConsole` by itself won't cover it. If you look at the sample code I posted in my original question, they do a whole bunch of adjustments for the C-type handles, stdout, stdin, stderr, etc. So I'm assuming all that has to be restored and file descriptors closed. So if you do all that and then call `FreeConsole` my approach of `attaching-only-when-you-need-it` actually works well. The only downside is that I can't use standard `printf`, or `cout` type methods and need to write my own. But it's basically a "find-and-replace' job for the source code... – ahmd0 Feb 21 '13 at 17:46
  • This is all technically unncessary. As shown in my deleted answer (viewable by those with enough rep) it is trivial to present the output from a GUI app in a console window, such that the GUI app continues happily when the console window is closed. So, upshot, solving the OP's problem is completely trivial, easy. – Cheers and hth. - Alf Feb 22 '13 at 09:47
0

I was able to resolve this issue by attaching to the parent console right before posting the text to the stdout stream and then by detaching from it. This way the text is posted alright and the console remains separate from my GUI app.

Here's the MFC/C++ class with the full implementation for those who want to use it.

ahmd0
  • 16,633
  • 33
  • 137
  • 233
  • consider that you could do that with all of 5 characters typed instead of all that source code etc., as i explained to you originally in a comment, and further explanded on when you asked, and illustrated with complete example source code, build example and run example in the answer that, due to the responses, i deleted – Cheers and hth. - Alf Feb 22 '13 at 10:31
  • You run the risk that the console will be closed whilst your GUI process is attached to it. – David Heffernan Mar 11 '13 at 21:57
  • @Cheersandhth.-Alf I came back to look at this. When the console is closed, it takes down `cat` process but leaves the other GUI subsystem process. Because the `cat` process is the one that's attached to the console. That's quite neat. I think that if you'd only explained that, your answer would have been well received. However, I do very much doubt that ahmd0 wants to always pipe the output. What's more doing so locks up the console. Which again I'm sure ahmd0 does not want. FWIW, in my view ahmd0 should not attempt to connect a GUI subsystem app to an existing console. It will lead to pain. – David Heffernan Mar 11 '13 at 22:04
  • @DavidHeffernan: Yes, I ran into issues with it. Not what you described, but mostly when someone using VBScript and ASP (classic) tries to read the `stdout` from my app or get `Exec.Status` the output is nothing or they get 0 for status. Too bad that GUI apps are so bad with console processes... – ahmd0 Mar 11 '13 at 22:11
  • A solution might be to have a separate console process that simply pipes all the input/output thru to a GUI app using a named pipe, or any other means of the IPC. This is a bigger pain in the a** to code but it seems that MS solutions don't really come with easy fixes... – ahmd0 Mar 11 '13 at 22:14