Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8030631
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 5, 20262026-06-05T00:50:01+00:00 2026-06-05T00:50:01+00:00

I have written a function that attempts to read a child process’s command line

  • 0

I have written a function that attempts to read a child process’s command line output via a pipe. This should be a simple subset of the MSDN Creating a Child Process with Redirected Input and Output article, but I am clearly making an error of some sort.

The ReadFile(…) call below blocks forever no matter if I place it before or after the WaitForSingleObject(…) call that should signal the end of the child process.

I have read all the answers that suggest “Use asynchronous ReadFile” and I am open to that suggestion if someone could give me some idea how that is accomplished on a pipe. Although I don’t understand why asynchronous I/O should be needed for this case.

#include "stdafx.h"
#include <string>
#include <windows.h>

unsigned int launch( const std::string & cmdline );

int _tmain(int argc, _TCHAR* argv[])
{
    launch( std::string("C:/windows/system32/help.exe") );  
    return 0;
}

void print_error( unsigned int err )
{
    char* msg = NULL;
    FormatMessageA(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        err,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPSTR)&msg,
        0, NULL );
    std::cout << "------ Begin Error Msg ------" << std::endl;
    std::cout << msg << std::endl;
    std::cout << "------  End Error Msg  ------" << std::endl;

    LocalFree( msg );
}

unsigned int launch( const std::string & cmdline )
{
    TCHAR cl[_MAX_PATH*sizeof(TCHAR)]; 
    memset( cl, 0, sizeof(cl) );
    cmdline.copy( cl, (_MAX_PATH*sizeof(TCHAR)) - 1);    

    HANDLE stdoutReadHandle = NULL;
    HANDLE stdoutWriteHandle = NULL;

    SECURITY_ATTRIBUTES saAttr; 
    memset( &saAttr, 0, sizeof(saAttr) ); 
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
    saAttr.bInheritHandle = TRUE; 
    saAttr.lpSecurityDescriptor = NULL; 

    // Create a pipe for the child process's STDOUT. 
    if ( ! CreatePipe(&stdoutReadHandle, &stdoutWriteHandle, &saAttr, 5000) )      
        throw std::runtime_error( "StdoutRd CreatePipe" ); 
    // Ensure the read handle to the pipe for STDOUT is not inherited.
    if ( ! SetHandleInformation(stdoutReadHandle, HANDLE_FLAG_INHERIT, 0) )
        throw std::runtime_error( "Stdout SetHandleInformation" ); 

    STARTUPINFO startupInfo; 
    memset( &startupInfo, 0, sizeof(startupInfo) ); 
    startupInfo.cb = sizeof(startupInfo);
    startupInfo.hStdError = stdoutWriteHandle;
    startupInfo.hStdOutput = stdoutWriteHandle;
    startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    startupInfo.dwFlags |= STARTF_USESTDHANDLES;

    char* rawEnvVars = GetEnvironmentStringsA();

    //__asm _emit 0xcc;

    PROCESS_INFORMATION processInfo;
    memset( &processInfo, 0, sizeof(processInfo) );

    std::cout << "Start [" << cmdline << "]" << std::endl;
    if ( CreateProcessA( 0, &cl[0], 0, 0, false, 
        CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, 
        rawEnvVars, 0, &startupInfo, &processInfo ) )
    {       
        //CloseHandle( stdoutWriteHandle );
        DWORD wordsRead;
        char tBuf[257] = {'\0'};
        bool success = true;
        std::string outBuf("");
        unsigned int t;
        while(success) {
            //__asm _emit 0xcc;
            std::cout << "Just before ReadFile(...)" << std::endl;
            success = ReadFile( stdoutReadHandle, tBuf, 256, &wordsRead, NULL);
            (t=GetLastError())?print_error(t):t=t;
            std::cout << "Just after ReadFile(...) | read " << wordsRead<< std::endl;
            std::cout << ".";
            if( success == false ) break;
            outBuf += tBuf;
            tBuf[0] = '\0';
        }
        std::cout << "output = [" << outBuf << "]" << std::endl;


        if ( WaitForSingleObject( processInfo.hProcess, INFINITE ) == WAIT_OBJECT_0 )
        {
            unsigned int exitcode = 0;
            GetExitCodeProcess( processInfo.hProcess, (LPDWORD)&exitcode );                
            std::cout << "exitcode = [" << exitcode << "]" << std::endl;

            //__asm _emit 0xcc;
            CloseHandle( processInfo.hProcess );
            CloseHandle( processInfo.hThread );

            return exitcode;
        }
    }
    else
    {
        DWORD procErr = GetLastError();
        std::cout << "FAILED TO CREATE PROCESS!" << std::endl;
        print_error( procErr );
    }
    return -1;
} // end launch()
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-05T00:50:04+00:00Added an answer on June 5, 2026 at 12:50 am

    There are a few bugs in your code, but the most important is that you’ve specified FALSE for the bInheritHandles argument to CreateProcess. The new process can’t use the pipe if it doesn’t inherit the handle to it. In order for a handle to be inherited, the bInheritHandles argument must be TRUE and the handle must have inheritance enabled.

    Other issues:

    • You’re specifying CREATE_UNICODE_ENVIRONMENT but passing an ANSI environment block. Note that it is easier to pass NULL for lpEnvironment and let the system copy the environment block for you. You should still specify CREATE_UNICODE_ENVIRONMENT in this case, as described in the documentation, because your environment block might contain Unicode characters.

    • Similarly, if you’re calling CreateProcessA you should be using STARTUPINFOA.

    • You don’t zero-terminate tBuf each time around the loop, so you’ll get spurious extra characters in your output buffer.

    • You need to close stdoutWriteHandle before you enter your read loop, or you won’t know when the subprocess exits. (Or you could use asynchronous IO and check for process exit explicitly.)

    • GetLastError() is undefined if an API function succeeds, so you should only be calling it if ReadFile returns FALSE. (Of course, in this case this is purely cosmetic since you aren’t acting on the error code.)

    For reference, here is my corrected version of your code. I’ve turned it into plain C (sorry!) because that’s what I’m familiar with. I compiled and tested in Unicode mode, but I think it should work without modification in ANSI mode too.

    #define _WIN32_WINNT _WIN32_WINNT_WIN7
    #include <windows.h>
    #include <stdio.h>
    
    void launch(const char * cmdline_in)
    {
        PROCESS_INFORMATION processInfo;
        STARTUPINFOA startupInfo; 
        SECURITY_ATTRIBUTES saAttr; 
    
        HANDLE stdoutReadHandle = NULL;
        HANDLE stdoutWriteHandle = NULL;
    
        char cmdline[256];
        char outbuf[32768];
        DWORD bytes_read;
        char tBuf[257];
    
        DWORD exitcode;
    
        strcpy_s(cmdline, sizeof(cmdline), cmdline_in);
    
        memset(&saAttr, 0, sizeof(saAttr));
        saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
        saAttr.bInheritHandle = TRUE; 
        saAttr.lpSecurityDescriptor = NULL; 
    
        // Create a pipe for the child process's STDOUT. 
        if (!CreatePipe(&stdoutReadHandle, &stdoutWriteHandle, &saAttr, 5000))
        {
            printf("CreatePipe: %u\n", GetLastError());
            return;
        }
    
        // Ensure the read handle to the pipe for STDOUT is not inherited.
        if (!SetHandleInformation(stdoutReadHandle, HANDLE_FLAG_INHERIT, 0))
        {
            printf("SetHandleInformation: %u\n", GetLastError());
            return;
        }
    
        memset(&startupInfo, 0, sizeof(startupInfo));
        startupInfo.cb = sizeof(startupInfo);
        startupInfo.hStdError = stdoutWriteHandle;
        startupInfo.hStdOutput = stdoutWriteHandle;
        startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
        startupInfo.dwFlags |= STARTF_USESTDHANDLES;
    
        // memset(&processInfo, 0, sizeof(processInfo));  // Not actually necessary
    
        printf("Starting.\n");
    
        if (!CreateProcessA(NULL, cmdline, NULL, NULL, TRUE,
            CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, NULL, 0, &startupInfo, &processInfo))
        {
            printf("CreateProcessA: %u\n", GetLastError());
            return;
        }
    
        CloseHandle(stdoutWriteHandle);
    
        strcpy_s(outbuf, sizeof(outbuf), "");
    
        for (;;) {
            printf("Just before ReadFile(...)\n");
            if (!ReadFile(stdoutReadHandle, tBuf, 256, &bytes_read, NULL))
            {
                printf("ReadFile: %u\n", GetLastError());
                break;
            }
            printf("Just after ReadFile, read %u byte(s)\n", bytes_read);
            if (bytes_read > 0)
            {
                tBuf[bytes_read] = '\0';
                strcat_s(outbuf, sizeof(outbuf), tBuf);
            }
        }
    
        printf("Output: %s\n", outbuf);
    
        if (WaitForSingleObject(processInfo.hProcess, INFINITE) != WAIT_OBJECT_0)
        {
            printf("WaitForSingleObject: %u\n", GetLastError());
            return;
        }
    
        if (!GetExitCodeProcess(processInfo.hProcess, &exitcode))
        {
            printf("GetExitCodeProcess: %u\n", GetLastError());
            return;
        }
    
        printf("Exit code: %u\n", exitcode);
    
        CloseHandle( processInfo.hProcess );
        CloseHandle( processInfo.hThread );
    
        return;
    }
    
    int main(int argc, char** argv)
    {
        launch("C:\\windows\\system32\\help.exe");
        return 0;
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have written a helper function that can retrieve content from a url. This
I have written this function that will give me a monthly sum for two
I have written a function that positions a tooltip just above a textbox. The
I have written a JS function that only allow numbers to be entered. A
I have written a javascript function that uses setInterval to manipulate a string every
I have written code to perform a function that could take a while to
I have written a PHP function to take a video embed code that has
I currently have a function written called saveWorkout that saves an NSMutableArray to another
There is a function I have written in C that I would like to
I have a 3500 lines long C function written by someone else that i

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.