ldr ldr - 3 months ago 18
C++ Question

Windows GUI as well as console apllication

I have an application that i want to be able to be run without arguments and a GUI or as a console application when there are arguments present.

int main(int argc, char *argv[])
{
if (argc > 1)
{
QCoreApplication app(argc, argv);
QTextStream out(stdout);
...
return app.exec();
}

else
{
QApplication app(argc, argv);
...
return app.exec();
}
}


This works fine under linux, but windows doesn't allow me to do any console output. After searching about the issue i found hints to AttachConsole() and reopening the output, so i added:

FreeConsole();
AttachConsole(ATTACH_PARENT_PROCESS);
freopen("CON", "w", stdout);
freopen("CON", "w", stderr);
freopen("CON", "r", stdin);


This works fine, except that after the application returns the commanline doesn't return to an "input state".
To clarify instead of this:

C:\Users\x>
hello world
C:\Users\x>


it's stuck like this:

C:\Users\x>
hello world


The application exits correctly, just cmd doesn't seem to know this.

So anybody can tell me what kind of cleanup i have to do there?

Answer

When the shell launches a console application from an interactive command line, it waits for the application to exit. That's necessary, because it prevents the application and the shell from competing for access to the console's input and output. This also means that the shell knows when to reprint the prompt.

When the shell launches a GUI application from an interactive command line, it doesn't wait. In this case, there's no need, and it would be inconvenient for the user. (It does wait when launching a GUI application from a batch file.)

(The user can override the default behaviour by using start with or without the /wait option.)

By using AttachConsole() you've subverted this mechanism, giving yourself access to the console while the shell believes nothing else is using it. This creates an inherent race condition - your output might wind up before, after, or intermingled with the shell prompt or with the output of other shell commands the user might run. (Also, if you wanted user input, there would be no reliable way to predict which input would go to the shell and which to your process.) The shell has no way to detect this condition and does not even attempt to do so.

The bottom line is that, unfortunately, there is no good way for a single executable to be suitable for both console and GUI use. Instead, create two executables, one for each scenario. If disk space is a concern, it is reasonably easy to make one of the executables very small, doing nothing but calling upon the other one. Better still, you can put the bulk of the application into a single DLL and have both executables load it.

Comments