win32 - 将控制台输出重定向到txt文本上
这里需要两个app.
parent.cpp
#include <Windows.h> #include <stdio.h> int main() { SECURITY_ATTRIBUTES se = {}; se.nLength = sizeof(SECURITY_ATTRIBUTES); se.bInheritHandle = true; se.lpSecurityDescriptor = NULL; HANDLE hFile = CreateFileW(L"test.txt", GENERIC_WRITE, FILE_SHARE_READ, &se, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); BOOL ret = SetStdHandle(STD_OUTPUT_HANDLE, hFile); printf("parent\n"); STARTUPINFO si = {}; si.cb = sizeof(STARTUPINFO); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); si.dwFlags |= STARTF_USESTDHANDLES; PROCESS_INFORMATION pi = {}; WCHAR cmd[] = L"child.exe"; CreateProcessW(cmd, NULL, 0, 0, 1, 0, 0, 0, &si, &pi); WaitForSingleObject(pi.hProcess, INFINITE); system("pause"); }
child.cpp
#include <stdio.h> #include <windows.h> int main() { DWORD lpMode; DWORD dwCount; HANDLE winout = GetStdHandle(STD_OUTPUT_HANDLE); BOOL is_console = GetConsoleMode(winout, &lpMode); int err = GetLastError(); if (is_console) { printf("Line 1 to console using printf.\n"); WriteConsoleA(winout, "Line 2 to console using WriteConsoleA.\n", 39, &dwCount, NULL); printf("Line 3 to console using printf.\n"); WriteConsoleA(winout, "Line 4 to console using WriteConsoleA.\n", 39, &dwCount, NULL); printf("Line 5 to console using printf.\n"); WriteConsoleA(winout, "Line 6 to console using WriteConsoleA.\n", 39, &dwCount, NULL); printf("Line 7 to console using printf.\n"); WriteConsoleA(winout, "Line 8 to console using WriteConsoleA.\n", 39, &dwCount, NULL); } else { printf("Line 1 to file using printf.\n"); fflush(stdout); WriteFile(winout, "Line 2 to file using WriteFile.\n", 32, &dwCount, NULL); printf("Line 3 to file using printf.\n"); fflush(stdout); WriteFile(winout, "Line 4 to file using WriteFile.\n", 32, &dwCount, NULL); printf("Line 5 to file using printf.\n"); fflush(stdout); WriteFile(winout, "Line 6 to file using WriteFile.\n", 32, &dwCount, NULL); printf("Line 7 to file using printf.\n"); fflush(stdout); WriteFile(winout, "Line 8 to file using WriteFile.\n", 32, &dwCount, NULL); } return 0; }
如果控制台句柄被定向,GetConsoleMode函数将会返回0,并得到err 6的错误信息,代表无效句柄。
并且如果将WriteConsole
与重定向到文件的标准句柄一起使用,则会失败。
参考:WriteConsole
所以我们需要使用WriteFile来输出,需要注意,如果没有fflush(),会输出
Line 2 to file using WriteFile. Line 4 to file using WriteFile. Line 6 to file using WriteFile. Line 8 to file using WriteFile. Line 1 to file using printf. Line 3 to file using printf. Line 5 to file using printf. Line 7 to file using printf.
会发现WriteFile先全部打印完,printf才开始打印。
因为当我们重定向到文件时,输出流将被会被完全缓冲,除非使用fflush(),否则将不会刷新该流,除非我们向其写入大量数据。
参考: Why does stdout need explicit flushing when redirected to file?