“printf”在Windows非控制台应用程序中写入的位置?

时间:2014-02-08 13:34:00

标签: c++ c winapi visual-c++ stdout

如果我选择创建Windows非控制台应用程序,并在代码中实现printf\cout,那么printf\cout会写在哪里?它是否写入stdout缓冲区?如果是的话,无论如何都要从stdout读取它并将其打印到某个文本文件或用文本做MessageBox(只是为了验证我是否已正确阅读)?

编辑:: 只是为了澄清我不想将输出重定向到任何地方。我想知道printf/cout写在哪里?如果它写入某个默认缓冲区,是否有办法读取输出,只是为了验证我已经从正确的缓冲区读取了正确的输出。 请不要给我解决方案来重定向“stdout”

4 个答案:

答案 0 :(得分:16)

在Windows下stdout是访问GetStdHandle(STD_OUTPUT_HANDLE)返回的句柄的低级函数的包装。

通过双击(我在Windows 7,64位下尝试)启动非控制台应用程序时,GetStdHandle(STD_OUTPUT_HANDLE)将返回无效句柄。这意味着printf和其他命令根本不会写入任何内容,但printf内部调用的低级函数将返回错误代码。

然而,正如已经说过的,甚至可以通过以下方式启动非控制台程序:

program_name > output_file.txt

在这种情况下,printf输出将写入输出文件。

- 编辑 -

如果您希望“捕获”printf()输出并将其写入MessageBox(),有两种方法可以实现此目的:

第一个是运行程序两次,而一个实例的输入是另一个实例的标准输出。可以通过以下命令行解释该行为:

program_name | program_name /msgbox

第二种可能性在没有运行两个程序且没有运行程序两次的情况下工作:您可以挂钩文件句柄#1。使用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,...);

答案 1 :(得分:11)

由于您的问题似乎仅供参考,因此没有控制台的Windows应用程序的stdout,stderr句柄已关闭。尝试输出到这些句柄的任何函数,只需调用,检查打开的句柄,找到它关闭,并返回而不做任何其他操作。

你可能会说,在这种情况下你的输出最终无处可寻:)

如果要读取此输出,则需要通过分配控制台或使用此处描述的方法之一来打开句柄。

答案 2 :(得分:4)

我正在开发一个可视引擎,我使用以下两个东西来代替你在控制台应用程序中获得的pc和用户之间的标准输入/输出。

1:使用sprintf (int sprintf ( char * str, const char * format, ... ))。它的作用是打印成一个字符串而不是stdout(你不必使用临时文件)。在此之后,您可以将MessageBox与您刚刚打印到的字符串一起使用。

2:创建一个实际的控制台窗口(同时保留主窗口)并将stdinstdoutstderr从主窗口重定向到控制台。这是一个建设课程:

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();
}

在此之后,调用printf()会将字符串打印到控制台中。您还可以使用控制台在其中键入字符串,它们可以在主窗口中使用(使用多线程,以便scanf不会暂停主程序。)

答案 3 :(得分:2)

printfcout始终打印到stdout

您需要从命令行启动程序并将其输出传递给文本文件以使其可读。

否则,您需要一个输出流到tmp中的文件,以便在代码中生成。

管道可以通过以下方式完成(如果您的应用名称为foo):

foo > log.txt

如果您导航到可以通过

找到的目录,则可以读取文件log.txt
dir