c++c++buildervclwinmain

Piping console output from WinMain when running from a console


I'm trying to pipe standard output from a WinMain function i a VCL forms application, from a console.

In particular, I need to do this in a console:

mywinprogram.exe -v > toMyFile.txt 

where the -v stands for version. The information passed on is simply the version of the application.

I'm able to get the output to the console using the answer here: How do I get console output in C++ with a Windows program?

but piping the output to a file don't work.

When started without any arguments, the application should behave like a 'normal' windows application.

The ability to get the information this way is for the workings of an automated build system.


Solution

  • This is a version of what I found in Sev's answer.

    Call this function the first thing you do in. _tWinMain():

    #include <cstdio>
    #include <fcntl.h>
    #include <io.h>
    
    void RedirectIOToConsole() {
        if (AttachConsole(ATTACH_PARENT_PROCESS)==false) return;
    
        HANDLE ConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
        int SystemOutput = _open_osfhandle(intptr_t(ConsoleOutput), _O_TEXT);
    
        // check if output is a console and not redirected to a file
        if(isatty(SystemOutput)==false) return; // return if it's not a TTY
    
        FILE *COutputHandle = _fdopen(SystemOutput, "w");
    
        // Get STDERR handle
        HANDLE ConsoleError = GetStdHandle(STD_ERROR_HANDLE);
        int SystemError = _open_osfhandle(intptr_t(ConsoleError), _O_TEXT);
        FILE *CErrorHandle = _fdopen(SystemError, "w");
    
        // Get STDIN handle
        HANDLE ConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
        int SystemInput = _open_osfhandle(intptr_t(ConsoleInput), _O_TEXT);
        FILE *CInputHandle = _fdopen(SystemInput, "r");
    
        //make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog point to console as well
        ios::sync_with_stdio(true);
    
        // Redirect the CRT standard input, output, and error handles to the console
        freopen_s(&CInputHandle, "CONIN$", "r", stdin);
        freopen_s(&COutputHandle, "CONOUT$", "w", stdout);
        freopen_s(&CErrorHandle, "CONOUT$", "w", stderr);
    
        //Clear the error state for each of the C++ standard stream objects.
        std::wcout.clear();
        std::cout.clear();
        std::wcerr.clear();
        std::cerr.clear();
        std::wcin.clear();
        std::cin.clear();
    }