How to Read Output from Cmd.Exe Using Createprocess() and Createpipe()

Redirecting I / O from cmd.exe using CreateProcess () and CreatePipe()

First, the error of ERROR_BROKEN_PIPE(109) caused by the cmd.exe exit unexpectedly. According to the sample Creating a Child Process with Redirected Input and Output:

The parent process uses the opposite ends of these two pipes to write
to the child process's input and read from the child process's output.
As specified in the STARTUPINFO structure, these handles are also
inheritable. However, these handles must not be inherited. Therefore,
before creating the child process, the parent process uses the
SetHandleInformation function to ensure that the write handle for
the child process's standard input and the read handle for the child
process's standard output
cannot be inherited.

You have set the other two handles to be un-inherited, so that cmd.exe exits without an available standard handle.

Set the pipe side of child process instead:

if (!SetHandleInformation(readFromCL, HANDLE_FLAG_INHERIT, 0)) {
cout << "SetHandleInformation error :: " << GetLastError() << endl;
}
if (!SetHandleInformation(writeToCL, HANDLE_FLAG_INHERIT, 0)) {
cout << "SetHandleInformation error :: " << GetLastError() << endl;
}

The issue of content size may because you need to wait for the output from cmd.exe. Add function like: Sleep(1000) before ReadFile Simply could solve it. Then, you could choose the most suitable method to synchronize the input and output of the two processes. Such as read in a for loop:

for (;;) {
memset(chBuff, '\0', deffBuffSize);
bSuccess = ReadFile(readFromCL, chBuff, deffBuffSize, &dRead, NULL);
if (!bSuccess || dRead == 0) {
break;
}
else {

cout << chBuff;
}
}

When outputting commands from cmd.exe (CreatProcess) I get More? Why and how to get rid of it?

The whole mistake was that I:

  1. Used "\0"
  2. WriteFile (writeToCL, outMes, sizeof (outMes) - 1, & dWrite, NULL)
    wrote two characters "\0"

This program endlessly enters and receives information about ipconfig

The command line takes the command like this: [i][p][c][o][n][f][i][g][\n][\0]

char outMes[] = "ipconfig\n";

for (;;) {
if (WriteFile(writeToCL, outMes, sizeof(outMes) - 1, &dWrite, NULL) == FALSE) {
cout << GetLastError() << " :: error WriteFile" << endl;
return 1;
}
Sleep(2000);
memset(chBuff, '\0', deffBuffSize);
if (ReadFile(readFromCL, chBuff, deffBuffSize, &dRead, NULL) == FALSE) {
cout << "ReadFile error :: " << GetLastError() << endl;
return 1;
}
cout << chBuff;

}

P.S: Use strlen to determine the length of a string.
instead sizeof()

Cannot read pipe from CreateProcess() thread

The child process is dying as soon as it attempts to read from standard input, because:

if (!SetHandleInformation(cmd_in_rd, HANDLE_FLAG_INHERIT, 0)) {

This should have been:

if (!SetHandleInformation(cmd_in_wr, HANDLE_FLAG_INHERIT, 0)) {

like in the original code.

Also, your error handling is largely incorrect; you don't consistently check for errors and you sometimes call GetLastError() when no error has occurred. (Those problems are in the original code too.)

You also need to put the call to CloseHandle(cmd_out_wr); back in because otherwise you won't be able to tell when the child exits.

Oh, and incidentally, cmd.exe is a process, not a thread.

CreateProcess and capture stdout

The short answer is to create an anonymous pipe, setting the hStdOut/hStdErr and dwFlag members of the STARTUPINFO structure accordingly, and have CreateProcess() inherit the handle for the writing end of the pipe. Don't forget to close your writing handle of your pipe, then you can read from the reading handle of the pipe in a loop until it fails with an ERROR_BROKEN_PIPE error.

MSDN provides a detailed example of this:

Creating a Child Process with Redirected Input and Output

You are not the first person to do this, there should be plenty of example code and duplicate questions here on StackOverflow.



Related Topics



Leave a reply



Submit