c++ - WinAPI - 如何将程序的所有标准输出和外部 DLL 重定向到 Win32 标准输出句柄?
问题描述
我希望能够将 Windows 应用程序的所有标准输出重定向到 Win32 标准输出句柄,而不是使用控制台句柄。
对于上下文,Emacs Win32 FAQ 是这样说的:
显式使用控制台句柄(CON 或 CON:)而不是 stdin 和 stdout 的程序不能用作 Emacs 的子进程,它们也不能在 shell 模式下工作 [...] Emacs 或在 shell 模式下使用的任何 shell 将此类进程的输入和输出从控制台重定向到输入和输出管道。唯一的解决方法是使用不直接使用控制台的程序的不同实现。(https://www.gnu.org/software/emacs/manual/html_node/efaq-w32/Subprocess-hang.html)
我遇到了常见问题解答描述的问题:从 Emacs 启动时,程序将运行,但shell
在程序退出之前,它的任何输出都不会显示在 Emacs 的窗口中,就好像 stdout 被缓冲并且在运行时没有刷新一样。cmd.exe
如果从或 ConEmu运行,相同的程序将按预期实时输出标准输出。
我想要完成的是让程序的所有输出都出现在 Emacs shell 中,这样我就可以在打印后立即跳转到编译器错误位置。我愿意重写程序的源代码来实现这一点。我想知道通过使用“stdin and stdout”而不是“控制台句柄”来完成此操作需要哪些“不同的实现”细节。
据我了解:
- Windows 中有多种 I/O,包括 C 运行时(
printf
等)和 Win32 层(ReadFile
等)。 - 我假设“stdin 和 stdout”指代
STD_INPUT_HANDLE
并且STD_OUTPUT_HANDLE
可以通过SetStdHandle()
. - 程序加载的外部 DLL 将继承 C 运行时
stdin
和stdout
管道,但这发生在程序初始化时,在调用任何调用之前SetStdHandle()
,因此您必须做一些其他事情来重定向它们的输出。
我试过使用这段代码:
#include <windows.h>
#include <cstdlib>
int main()
{
HANDLE hStdout = CreateFile(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE hStdin = CreateFile(L"CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
SetStdHandle(STD_OUTPUT_HANDLE, hStdout);
SetStdHandle(STD_ERROR_HANDLE, hStdout);
SetStdHandle(STD_INPUT_HANDLE, hStdin);
std::cout << "Hello, world." << std::endl;
printf("Hello, world.\n");
std::cin.get();
return 0;
}
这具有预期的效果,但仅限于与重定向代码相同的二进制文件的用法printf
和内部。std::cout
我的程序加载了一个使用的外部 DLL,printf
并且它的任何输出都没有被重定向。
另外,我不想使用AllocConsole()
或类似,因为它会打开一个单独的窗口,该窗口不与父进程(Emacs)集成。我想要的是重定向所有标准输出,以便它显示在运行程序的同一个终端/控制台中,而不是另一个窗口(如果有意义的话)。由于我不使用AllocConsole()
,所以代码_open_osfhandle((long)hStdout, O_WRONLY|O_TEXT)
总是-1
由于某种原因返回,所以看起来我不能像这里dup2()
描述的那样使用。
也可以看看:
解决方案
我使用了上面提供的代码示例,然后调用setvbuf(stdout, NULL, _IONBF, 4096)
以设置非缓冲输出并获得所需的结果。
推荐阅读
- html - 使用 office-ui-fabric 的 ms-hidden 类的问题
- sql - 在 MS Azure SQL 数据库中执行 case 语句时出现数据类型不匹配错误
- reactjs - 设置 React Material UI Checkbox 数据属性
- python - Python 在命令行上启动程序后我无法转向我的代码
- google-cloud-firestore - Algolia Livesearch 将 Firestore 数据索引到 Algolia
- angular - 尝试安装 Angular 时,找不到 ng 命令
- python - 我需要删除所有使用不同索引重复的行
- angular - Angular 7 CanActivate Guard for URL
- angular - 如何在 ion-content 中渲染从 API 加载的 html
- python - 将行插入熊猫数据框中的随机位置