"printf"在 Windows 非控制台应用程序中写入何处?

Where does "printf" write in a Windows Non-console Application?

本文关键字:何处 控制台 printf Windows 应用程序      更新时间:2023-10-16

如果我选择创建一个Windows非控制台应用程序,并在代码中实现printf/cout,那么printf/cout写在哪里?它是否写入stdout缓冲区?如果是,有没有办法从stdout中读取并打印到某个文本文件,或者用文本做MessageBox(只是为了验证我是否正确读取了它)?

编辑::只是澄清一下,我不想将输出重定向到任何地方。我想知道,printf/cout写在哪里?如果它写入某个默认缓冲区,是否有一种方法可以读取输出,只是为了验证我是否读取了正确的输出以及从正确的缓冲区中读取请不要给我重定向";stdout">

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

当双击启动非控制台应用程序时(我在Windows764位下尝试过),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,...);

由于您的问题似乎只是为了提供信息,一个没有控制台的windows应用程序关闭了stdout、stderr句柄。任何试图输出到这些句柄的函数,只要被调用,检查一个打开的句柄,发现它是关闭的,然后返回而不做任何其他操作。

你可能会说,在这种情况下,你的输出最终找不到:)

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

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

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

2:制作一个实际的控制台窗口(同时保留主窗口),并将stdinstdoutstderr从主窗口重定向到控制台。这里有一个建筑类:

控制台窗口类.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();
};

控制台窗口类.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就不会暂停主程序)。

printfcout始终打印到stdout

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

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

管道可以通过以下方式完成(如果你的应用程序名称是foo):

foo > log.txt

然后,如果你导航到文件log.txt的目录,你可以通过找到它

dir