[Qt-interest] stdout of MSWin GUI application run from console

Graeme Gill graeme2 at argyllcms.com
Wed Apr 27 14:27:26 CEST 2011


Here's another update to this code, with a minor fix to make
it run properly on Vista and Win7.

As was hinted by a previous responder, it seems that Microsoft
changed cmd.exe in Vista and Win7 so that if you start a
GUI application from the command line, it doesn't wait for it to
exit (ie. it acts like "$ app.exe&" would with a Unix shell). This
behaviour can be avoided by either changing the cmd.exe shortcut
to start it with extensions off (ie. "cmd.exe /E:OFF"), or starting
the GUI application using one of the following ways:

   start /wait app.exe
   cmd /C app.exe

[This code seems to work as expected with 64 bit applications too.]

Graeme Gill.

-------------------------------------------------------------------
#include <QApplication>
#include <stdio.h>
#include "tdialog.hpp"

#ifdef Q_WS_WIN
#include <windows.h>

void winConsoleMsgHandler(QtMsgType t, const char* str) {
         fprintf(stderr, "%s\n", str);
         fflush(stderr);
}
#endif // Q_WS_WIN

int main(int argc, char *argv[]) {

#ifdef Q_WS_WIN
     {
         BOOL (WINAPI *AttachConsole)(DWORD dwProcessId);

         AttachConsole = (BOOL (WINAPI*)(DWORD))
             GetProcAddress(LoadLibraryA("kernel32.dll"), "AttachConsole");

             if (AttachConsole != NULL && AttachConsole(((DWORD)-1))) {
                 if (_fileno(stdout) < 0)
                     freopen("CONOUT$","wb",stdout);
                 if (_fileno(stderr) < 0)
                     freopen("CONOUT$","wb",stderr);
                 if (_fileno(stdin) < 0)
                     freopen("CONIN$","rb",stdin);

                 // Fix C++
                 std::ios::sync_with_stdio();

                 // Fix messages
                 qInstallMsgHandler(winConsoleMsgHandler);
             }
     }
#endif // Q_WS_WIN

     printf("This is stdout\n");
     fprintf(stderr,"This is stderr\n");
     qDebug("This is a qDebug message");

     QApplication app(argc, argv);
     TDialog *dialog = new TDialog;
     dialog->show();

     qDebug("This is another qDebug message");

     return app.exec();
}

-------------------------------------------------------------------
*** src/corelib/kernel/qcoreapplication_win.cpp Thu Apr 14 11:17:48 2011
--- src/corelib/kernel/qcoreapplication_win.cpp Thu Apr 14 12:14:09 2011
*************** void qWinMain(HINSTANCE instance, HINSTA
*** 181,191 ****
           qWarning("Qt: Internal error: qWinMain should be called only once");
           return;
       }
       already_called = true;
-     usingWinMain = true;

!     // Install default debug handler
!     qInstallMsgHandler(qWinMsgHandler);

       // Create command line
       argv = qWinCmdLine<char>(cmdParam, int(strlen(cmdParam)), argc);
--- 181,214 ----
           qWarning("Qt: Internal error: qWinMain should be called only once");
           return;
       }
+
       already_called = true;

! #ifdef Q_WS_WIN
!   // Re-attach stdio if application was started from a console
!   BOOL (WINAPI *pAttachConsole)(DWORD dwProcessId);
!
!   pAttachConsole = (BOOL (WINAPI*)(DWORD))
!       GetProcAddress(LoadLibraryA("kernel32.dll"), "AttachConsole");
!
!   if (pAttachConsole != NULL && pAttachConsole(((DWORD)-1))) {
!       if (_fileno(stdout) < 0)
!           freopen("CONOUT$","wb",stdout);
!       if (_fileno(stderr) < 0)
!           freopen("CONOUT$","wb",stderr);
!       if (_fileno(stdin) < 0)
!           freopen("CONIN$","rb",stdin);
!
!       // Fix C++
!       std::ios::sync_with_stdio();
!   } else
! #endif // Q_WS_WIN
!   {
!       usingWinMain = true;    // Reset to qWinMsgHandler on qInstallMsgHandler(0)
!
!       // Install default debug handler
!       qInstallMsgHandler(qWinMsgHandler);
!   }

       // Create command line
       argv = qWinCmdLine<char>(cmdParam, int(strlen(cmdParam)), argc);



More information about the Qt-interest-old mailing list