c++ - 在win32中重定向标准输出不会重定向标准输出
问题描述
我正在尝试重定向标准输出,以便 Windows 应用程序中的 printf 将转到我选择的文件。
我正在这样做:
outFile = fopen("log.txt", "w");
*stdout = *outFile;
setvbuf(stdout, NULL, _IONBF, 0);
但 printf 仍然写入控制台(或者在基于 GUI 的 win32 应用程序上无处)
我可以通过这样做重定向“std::cout”:
outFileStr = std::ofstream(outFile);
std::cout.rdbuf(outFileStr.rdbuf());
但是 printf 似乎在做自己的事情。不幸的是,我需要重定向 printf,因为我正在尝试将 python 集成到 C++ 框架中,并且这似乎依赖于 printf 而不是 std::cout。
std::cout' 似乎被重定向但不是 printf。
解决方案
由于缺乏适当的接口来映射任意 Win32 文件句柄和更高层文件描述符/流,重定向标准 I/O 在 Windows 上涉及更多。
Windows 上实际上存在三个不同的 I/O 层:
- 标准?CI/O 流(这些由
printf
,scanf
, ... 使用) - POSIX I/O 描述符(这些是由
read
,write
, ... 使用的整数) - Win32 API I/O 句柄(由
ReadFile
,WriteFile
, ... 使用)
重定向 C 流
要重定向 C 流,您可以使用freopen
. 例如,您可以stdout
使用以下命令重定向 C:
freopen("log.txt", "w", stdout);
这种重定向通常不会重定向由 POSIX 或 Win32 API 完成的 I/O(如果有的话,它们仍然会读/写附加的控制台)。另外,这个重定向不会被子进程继承。(在 POSIX 兼容/非 Windows 系统上,通常 POSIX API 也是系统 API,而 C API 是在 POSIX API 之上实现的。在这些情况下,freopen
就足够了。)
重定向 POSIX I/O 描述符
要在 POSIX API 级别重定向 I/O,您可以使用dup2
. 例如,您可以将文件描述符重新分配STDOUT_FILENO
给 redirect stdout
,例如:
int fd = open("log.txt", O_WRONLY);
dup2(fd, STDOUT_FILENO);
close(fd);
不幸的是,在 Windows 上,即使是 POSIX API 级别的重定向也不能保证 C 和 Win32 API 级别的重定向。这是否可行取决于 C 库的实现在 POSIX 文件描述符和 Win32 文件句柄之间映射的努力(假设您使用的 C 运行时库将其 I/O 分层在 POSIX 之上开始) . 也不能保证这个重定向会被衍生的孩子继承。
在 Windows 上重定向标准 I/O!
要在 Windows 上正确重定向 I/O,您必须在最低级别(即 Win32 API 级别)重定向并在更高级别修复链接,如下所示:
- 通过调用分配一个新句柄
CreateFile
。 - 使用 .将该新句柄分配给所需的 std I/O 设备
SetStdHandle
。 _open_osfhandle
使用(返回文件描述符编号)将该新句柄与相应的 C std 文件描述符相关联。dup2
使用上述技术重定向返回的文件描述符。
这是重定向的示例片段stdout
:
HANDLE new_stdout = CreateFileA("log.txt", ...);
SetStdHandle(STD_OUTPUT_HANDLE, new_stdout);
int fd = _open_osfhandle(new_stdout, O_WRONLY|O_TEXT);
dup2(fd, STDOUT_FILENO);
close(fd);
PS 如果您可以在程序内部不进行 I/O 重定向,那么您可以使用控制台的 I/O 重定向在命令行中使用一个很小的批处理文件:
@echo off
start "my_gui_app" "path/to/my_gui_app.exe" 1> "path/to/log.txt"
推荐阅读
- python - 如何在python中创建reduce()
- javascript - Javascript从另一个元素中找到最接近的h2
- odoo-12 - 如何在 Odoo POS v12 中添加选定的客户图像
- python - 使用 OneHotEncoding 更改分类变量的问题
- pytorch - 如何在 pytorch 1.1.0 JIT 编译器中启用 Dict/OrderedDict/NamedTuple 支持?
- perl - 获取 Perl 打包/解包模板的元素数量
- postgresql - 性能注意事项 JSONB 上的 Postgresql 物化视图。有没有替代品
- swift - 第二次生成没有完全相同数字的随机数
- here-api - 如何创建只有法线地图和卫星视图的 HERE 地图,没有额外的图层?
- google-chrome - (Google chrome & Angular7) 不显示打字稿源代码