locked
Use SetStdHandle to redirect stdout and stderr RRS feed

  • Question

  • I am attempting to capture my own program's output to parse later (don't ask). In using SetStdHandle to achieve this I am getting odd behavior.

    In the following code I am seeing "HelloHi?" on the console while I would expect "Hi?".  I am seeing "Ha!" when I read from the pipe.

    oldStdOutHandle is different from stdOutWrite.  xstdout is the same as stdOutWrite.

    It appears that while Get/SetStdHandle thinks that the stdout has been retargeted, but I am not seeing any indication from program behavior that it has happened.

    I also attempted to flush stdout before calling SetStdHandle, and that didn't change behavior

    What is happening, and how can I fix this?  I am using VS2015 Update 2 on Windows 10.

    HANDLE stdOutRead = INVALID_HANDLE_VALUE;
    HANDLE stdOutWrite = INVALID_HANDLE_VALUE;
    
    SECURITY_ATTRIBUTES securityAttributes;
    securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
    securityAttributes.lpSecurityDescriptor = nullptr;
    securityAttributes.bInheritHandle = TRUE;
    
    ASSERT_NE(0, CreatePipe(&stdOutRead, &stdOutWrite, &securityAttributes, 0));
    auto g1 = CreateScope([&]() {
       CloseHandle(stdOutRead);
       CloseHandle(stdOutWrite);
    });
    
    HANDLE oldStdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    ASSERT_NE(INVALID_HANDLE_VALUE, oldStdOutHandle);
    ASSERT_NE(0, SetStdHandle(STD_OUTPUT_HANDLE, stdOutWrite));
    auto g3 = CreateScope([&]() { SetStdHandle(STD_OUTPUT_HANDLE, oldStdOutHandle); });
    HANDLE xstdout = GetStdHandle(STD_OUTPUT_HANDLE);
    
    std::cout << "Hello";
    DWORD x;
    WriteFile(stdOutWrite, "Ha!", 3, &x, nullptr);
    WriteFile(oldStdOutHandle, "Hi?", 3, &x, nullptr);

    Thursday, April 21, 2016 8:55 PM

Answers

  • On 4/21/2016 4:55 PM, diltsman wrote:

    I am attempting to capture my own program's output to parse later (don't ask). In using SetStdHandle to achieve this I am getting odd behavior.

    In the following code I am seeing "HelloHi?" on the console while I would expect "Hi?".  I am seeing "Ha!" when I read from the pipe.

    stdout and std::cout are created and bound to the standard handle before main() is even entered. They don't re-query the handle on every output operation, or anything along these lines.

    You could try and make stdout aware of the handle change by a combination of _open_osfhandle, _fileno and _dup2. This should fix things like printf(). Not sure if that's enough to also redirect std::cout.

    • Marked as answer by diltsman Thursday, April 21, 2016 10:10 PM
    Thursday, April 21, 2016 9:45 PM