win32

这里需要两个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
");
    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.
");
        WriteConsoleA(winout, "Line 2 to console using WriteConsoleA.
", 39, &dwCount, NULL);
        printf("Line 3 to console using printf.
");
        WriteConsoleA(winout, "Line 4 to console using WriteConsoleA.
", 39, &dwCount, NULL);
        printf("Line 5 to console using printf.
");
        WriteConsoleA(winout, "Line 6 to console using WriteConsoleA.
", 39, &dwCount, NULL);
        printf("Line 7 to console using printf.
");
        WriteConsoleA(winout, "Line 8 to console using WriteConsoleA.
", 39, &dwCount, NULL);
    }
    else {
        printf("Line 1 to file using printf.
");
        fflush(stdout);
        WriteFile(winout, "Line 2 to file using WriteFile.
", 32, &dwCount, NULL);
        printf("Line 3 to file using printf.
");
        fflush(stdout);
        WriteFile(winout, "Line 4 to file using WriteFile.
", 32, &dwCount, NULL);
        printf("Line 5 to file using printf.
");
        fflush(stdout);
        WriteFile(winout, "Line 6 to file using WriteFile.
", 32, &dwCount, NULL);
        printf("Line 7 to file using printf.
");
        fflush(stdout);
        WriteFile(winout, "Line 8 to file using WriteFile.
", 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?

原文地址:https://www.cnblogs.com/strive-sun/p/14331328.html