Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>There are a few bugs in your code, but the most important is that you've specified <code>FALSE</code> for the <code>bInheritHandles</code> argument to <code>CreateProcess</code>. 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 <code>bInheritHandles</code> argument must be <code>TRUE</code> <em>and</em> the handle must have inheritance enabled.</p> <p>Other issues:</p> <ul> <li><p>You're specifying <code>CREATE_UNICODE_ENVIRONMENT</code> but passing an ANSI environment block. Note that it is easier to pass <code>NULL</code> for <code>lpEnvironment</code> and let the system copy the environment block for you. You don't need to specify CREATE_UNICODE_ENVIRONMENT in this case, even if you're compiling in Unicode mode.</p></li> <li><p>Similarly, if you're calling CreateProcessA you should be using STARTUPINFOA.</p></li> <li><p>You don't zero-terminate <code>tBuf</code> each time around the loop, so you'll get spurious extra characters in your output buffer.</p></li> <li><p>You need to close <code>stdoutWriteHandle</code> 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.)</p></li> <li><p><code>GetLastError()</code> is undefined if an API function succeeds, so you should only be calling it if <code>ReadFile</code> returns <code>FALSE</code>. (Of course, in this case this is purely cosmetic since you aren't acting on the error code.)</p></li> </ul> <p>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.</p> <pre><code>#define _WIN32_WINNT _WIN32_WINNT_WIN7 #include &lt;windows.h&gt; #include &lt;stdio.h&gt; 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(&amp;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(&amp;stdoutReadHandle, &amp;stdoutWriteHandle, &amp;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(&amp;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(&amp;processInfo, 0, sizeof(processInfo)); // Not actually necessary printf("Starting.\n"); if (!CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, 0, &amp;startupInfo, &amp;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, &amp;bytes_read, NULL)) { printf("ReadFile: %u\n", GetLastError()); break; } printf("Just after ReadFile, read %u byte(s)\n", bytes_read); if (bytes_read &gt; 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, &amp;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; } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload