23

If I choose to create a Windows Non-console Application, and implement printf/cout in the code, where does the printf/cout write? Does it write to the stdout buffer? If yes, is there any way to read it from stdout and print it to some text file or do a MessageBox with the text (just to verify that I have read it correctly)?

EDIT:: Just to clarify that I do not want to redirect the output anywhere. I would like to know, where does printf/cout write? And if it writes to some default buffer, is there a way to read the output, just to verify that I have read the correct output and from the correct buffer. Please, do not give me solutions to redirect the "stdout".

Jens
  • 69,818
  • 15
  • 125
  • 179
Abhineet
  • 5,320
  • 1
  • 25
  • 43
  • 4
    Technically it doesn't write anywhere but you may redirect it to text file by using `freopen("file.txt","w",stdout);` – Predelnik Feb 08 '14 at 13:37
  • 1
    possible duplicate of [How can I redirect stdout to some visible display in a Windows Application?](http://stackoverflow.com/questions/573724/how-can-i-redirect-stdout-to-some-visible-display-in-a-windows-application) – Martin R Feb 08 '14 at 13:52
  • 1
    @MartinR:: I don't want to redirect the output. I want to know, where does it write if not redirected and is there a way to read that location to verify. – Abhineet Feb 08 '14 at 14:08
  • You can read the output with `nonconsole.exe | tee`. tee is included in "Git for Windows". – elsamuko Mar 09 '17 at 12:30

4 Answers4

20

Under Windows stdout is a wrapper to the low-level functions accessing the handle returned by GetStdHandle(STD_OUTPUT_HANDLE).

When starting a non-console application by double-clicking (I tried under Windows 7, 64 bit) then GetStdHandle(STD_OUTPUT_HANDLE) will return an invalid handle. This means that printf and other commands will write nothing at all but the low-level functions internally called by printf will return an error code.

However as already said even a non-console program can be started the following way:

program_name > output_file.txt

In this case the printf output will be written to the output file.

-- EDIT --

If you wish to "catch" the printf() output and write it to MessageBox() there are two ways to achieve this:

The first one is running the program twice while the input of one instance is the standard output of the other one. The behavior could be explained by the following command line:

program_name | program_name /msgbox

The second possibility works without running two programs and without running the program twice: You may hook file handle #1. This should be at least possible when using msvcrt.dll:

HANDLE hRead,hWrite;

CreatePipe(&hRead,&hWrite,NULL,0);
dup2(_open_osfhandle(hWrite,O_WRONLY),1);

// Now printf() output can be read from handle hRead

printf("Hello world 2!\n");

// In a separate thread do:
ReadFile(hRead,...);
Abhineet
  • 5,320
  • 1
  • 25
  • 43
Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38
12

Since your question seems to be just for information, a windows app without a console, has its stdout, stderr handles closed. Any function that tries to output to those handles, simply gets called, checks for an open handle, finds it closed, and returns without doing anything else.

You might say, your output in this case ends up nowhere to be found :)

If you want to read this output, then you need to open the handles either by allocating a console, or use one of the methods described here.

DNT
  • 2,356
  • 14
  • 16
4

I am developing a visual engine and I use the following two things as a substitution for the standard input/output between pc and user that you get in console application.

1: Use sprintf (int sprintf ( char * str, const char * format, ... )). What it does is print into a string instead of stdout(you don't have to use a temporary file). After this you can use MessageBox with the string where you just printed to.

2: Make an actual console window(while keeping the main one) and redirect the stdin, stdout and stderr from the main window to the console. Here is a class for construction:

ConsoleWindowClass.h:

 #pragma once
 #include <windows.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <io.h>
 #include <iostream>
 #include <fstream>
class ConsoleWindowClass
{
public:
    ConsoleWindowClass(void);
    ~ConsoleWindowClass(void);
    void Create();
};

ConsoleWindowClass.cpp:

 #include "ConsoleWindowClass.h"

using namespace std;

// maximum mumber of lines the output console should have
static const WORD MAX_CONSOLE_LINES = 500;

ConsoleWindowClass::ConsoleWindowClass(void)
{
    Create();
}

ConsoleWindowClass::~ConsoleWindowClass(void)
{
}

void ConsoleWindowClass::Create()
{
    int hConHandle;
    long lStdHandle;
    CONSOLE_SCREEN_BUFFER_INFO coninfo;
    FILE *fp;

// allocate a console for this app
    AllocConsole();

// set the screen buffer to be big enough to let us scroll text
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&coninfo);
    coninfo.dwSize.Y = MAX_CONSOLE_LINES;
    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
    ios::sync_with_stdio();
}

After this, calling printf() will print the string into the console. You can also use the console to type strings into it and they will be usable from the main window(use multi-threading so that scanf won't pause your main program).

Abhineet
  • 5,320
  • 1
  • 25
  • 43
Vladivarius
  • 498
  • 1
  • 3
  • 14
  • If you want to use just C and not C++, you can cut out the and the ios::sync_with_stdio(). You will also have to do it without a class. Here is what the last line does: http://www.cplusplus.com/reference/ios/ios_base/sync_with_stdio/ – Vladivarius Feb 08 '14 at 14:00
  • Yeah, I understood the question after I wrote the answer. Anyway, this will hopefully serve someone looking for redirection :) – Vladivarius Feb 08 '14 at 15:12
2

printf or cout always print to stdout.

You need to start the program from command line and pipe its output to a text file to make it readable.

Otherwise you would need an outputstream to a file in tmp to be generated inside your code.

Piping can be done the following way (if your apps name would be foo):

foo > log.txt

You could then read the file log.txt if you navigate to its directory which can be found with

dir
Abhineet
  • 5,320
  • 1
  • 25
  • 43
Heiko Becker
  • 556
  • 3
  • 16