Where does "printf" write in a Windows Non-console Application?
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
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.
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,...);
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).