Command line + GUI

Hey guys,

I want to create an application that both works on the command line (without GUI!) and as a GUI program. So, I tried this (on windows):

    void initialise (const String& commandLine)
    {
        if (commandLine.length() != 0)
        {
            Logger::outputDebugString("Hello from outputDebugString\n");
            std::cout << "Hello from cout" << std::endl;
            JUCEApplication::quit();
        }
        else
        {
            mainWindow = new MainAppWindow();
        }
    }

In my JUCEApplication class. However, no output appears, neither in Debug or in Release mode.
Any hints would be nice!

  • bram

sigh it looks like in windows GUI apps can’t print on the command line.
dammit windows!

  • bram

You need to spawn a new console.

This is necessary particularly as GUI/CLI hybrid apps are going to appear identical when launched from an icon with extra parameters.

Here’s what I do in an app where I’m doing the same thing:

#ifdef _WIN32

  // Code taken from here: http://dslweb.nwnexus.com/~ast/dload/guicon.htm
  // Modified to support attaching to an owner console.
  void redirectIOToConsole()
  {
    int hConHandle;
    long lStdHandle;
    FILE *fp;
    if (AttachConsole(ATTACH_PARENT_PROCESS) == 0)
    {
      // We couldn't obtain a parent console.  Probably application was launched 
      // from inside Explorer (E.G. the run prompt, or a shortcut).
      // We'll spawn a new console window instead then!
      CONSOLE_SCREEN_BUFFER_INFO coninfo;
      AllocConsole();
      GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
      coninfo.dwSize.Y = 500;
      SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
    }
    // redirect unbuffered STDOUT to the console
    lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    fp = _fdopen( hConHandle, "w" );
    *stdout = *fp;
    setvbuf( stdout, NULL, _IONBF, 0 );
    // redirect unbuffered STDIN to the console
    lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    fp = _fdopen( hConHandle, "r" );
    *stdin = *fp;
    setvbuf( stdin, NULL, _IONBF, 0 );
    // redirect unbuffered STDERR to the console
    lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    fp = _fdopen( hConHandle, "w" );
    *stderr = *fp;
    setvbuf( stderr, NULL, _IONBF, 0 );
    // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
    // point to console as well
    std::ios::sync_with_stdio();
  }

#else

  // Empty function avoid ifdefs elsewhere.
  void redirectIOToConsole() {}

#endif

In my initializer I just call redirectToConsole() which starts the whole deal up on Windows, or nothing much everywhere else. After that, std::cout and std::err work as expected.

Hey thanks Valley, and nope, I never saw this post. I suppose I chucked the mail in the garbage can :slight_smile:

I’ll give this a try!

  • bram