我正在尝试创build一个函数来生成一个程序的实例,然后将一些数据input到STDIN中,然后使用C ++读取进程的输出。 我看了一个位于这里的MSDN示例,这让我感到困惑,当我尝试使用该示例时,出现了一些令人讨厌的错误代码,并且无法正常工作。
HANDLE hWriteOUT, hReadOUT, hWriteIN, hReadIN; SECURITY_ATTRIBUTES saPipe = {0}; PROCESS_INFORMATION procInfo = {0}; STARTUPINFO procSi; DWORD dwWritten, dwRead; char buf[512]; saPipe.nLength = sizeof(SECURITY_ATTRIBUTES); saPipe.bInheritHandle = TRUE; saPipe.lpSecurityDescriptor= NULL; CreatePipe(&hReadOUT, &hWriteOUT, &saPipe, 0); SetHandleInformation(hReadOUT, HANDLE_FLAG_INHERIT, 0); CreatePipe(&hReadIN, &hWriteIN, &saPipe, 0); SetHandleInformation(hReadIN, HANDLE_FLAG_INHERIT, 0); ZeroMemory(&procSi, sizeof(STARTUPINFO)); procSi.cb = sizeof(STARTUPINFO); procSi.hStdError = hWriteOUT; procSi.hStdOutput = hWriteOUT; procSi.hStdInput = hReadIN; procSi.dwFlags |= STARTF_USESTDHANDLES; CreateProcess(NULL, "cmd", NULL, NULL, TRUE, 0, NULL, NULL, &procSi, &procInfo); //Gives me an error code of 18 but returns a 1 when a 0 indicates failure. WriteFile(hWriteIN, "notepad", sizeof("notepad"), &dwWritten, NULL); cout << GetLastError(); //This gives me error code 18 (ERROR_NO_MORE_FILES) ReadFile(hReadOUT, buf, 512, &dwRead, NULL); cout << buf; //This prints "Microsoft Windows [version 6.1.7601] CloseHandle(hWriteIN);
该代码无法将string“记事本”传送到cmd.exe,但成功启动了命令shell程序。 如果我查看任务pipe理器,有几个命令提示符的实例,但没有记事本。 另外, ReadFile()
函数是唯一一个看起来有效的函数,但它甚至不是从pipe道进程读取(本来应该生成的记事本),而是从CMD中读取。 更糟糕的是,它只能截断所有内容,而不是第一行。 (CMD打印“Microsoft Windows …. \ n版权… \ n C:\ Users \ Foo> … \ n”但ReadFile()只抓取第一行)
代码的行为如预期。 你似乎有一些误解:
1)如果您希望cmd.exe运行,您需要在命令末尾发送一个ENTER(“\ n”)。 通常,最好在CreateProcess中指定要运行的命令,例如,可以将“cmd / c notepad”指定为命令行而不是“cmd”。
2)您已经将管道连接到cmd.exe进程的标准输入和输出,所以当然您会看到该进程的输出。 如果您不想查看cmd.exe的输出,请不要运行它; 直接运行你想要的应用程序,例如,你可以指定“记事本”作为命令行来运行。
3)从管道读取时, ReadFile一次只返回一个数据块,所以需要循环调用它。
4)记事本是一个GUI过程,所以它不使用标准输入或标准输出。 据推测,这只是一个选择不好的例子,你真的想运行一个命令行应用程序?
5)除了具体记录,错误代码(由GetLastError返回)只有在函数失败时才有意义。 你所使用的函数都不是这种情况的例外,所以检查错误代码是没有意义的,除非函数返回0来表示它失败了。
我知道回答这个问题还为时过晚,但是你的代码也有其他问题。 看来SetHandleInformation(hReadOUT, HANDLE_FLAG_INHERIT, 0);
和SetHandleInformation(hReadIN, HANDLE_FLAG_INHERIT, 0);
会打破东西。 我不知道为什么,但尝试运行你的代码后,cmd无法读取管道的值,直到我删除这两行。