我创建了两个管道来将子进程stdin和stdout重定向到父进程,如下所示 http://msdn.microsoft.com/en-us/library/ms682499%28VS.85%29.aspx
子进程是一个exe文件。 当使用控制台执行时,它首先在STDOUT上返回一个警告,然后从STDIN请求是/否输入。 当我从我的cpp程序运行子进程时,读取管道成功地从子进程STDOUT读取警告线但是当尝试使用写入管道向子进程发送“是”或“否”时,子程序以某种方式不接收它。但是当我在父级的STDIN上键入它时,子进程收到yes和no。
知道为什么会这样吗?
答案 0 :(得分:0)
您是否有儿童计划的来源?检查它是如何读取输入的(或在此处发布源代码)。
您的子程序是否可以使用cmd输入重定向,例如如果你做echo yes | childprogram.exe
?
如果没有,则程序可能会使用低级别console functions来进行输入(可能是间接的,例如通过_getch()
)。在这种情况下,您可能必须使用WriteConsoleInput来模拟输入。
或者,您的重定向代码可能存在错误。发布在这里。
编辑使用WriteConsoleInput:
的示例#include <windows.h>
#include <process.h>
#include <stdlib.h>
#include <stdio.h>
static const INPUT_RECORD SimulatedInput [] =
{
{KEY_EVENT, {TRUE, 1, 0, 0, {L'e'}, 0}},
{KEY_EVENT, {TRUE, 1, 0, 0, {L'c'}, 0}},
{KEY_EVENT, {TRUE, 1, 0, 0, {L'h'}, 0}},
{KEY_EVENT, {TRUE, 1, 0, 0, {L'o'}, 0}},
{KEY_EVENT, {TRUE, 1, 0, 0, {L' '}, 0}},
{KEY_EVENT, {TRUE, 1, 0, 0, {L'T'}, 0}},
{KEY_EVENT, {TRUE, 1, 0, 0, {L'E'}, 0}},
{KEY_EVENT, {TRUE, 1, 0, 0, {L'S'}, 0}},
{KEY_EVENT, {TRUE, 1, 0, 0, {L'T'}, 0}},
{KEY_EVENT, {TRUE, 1, VK_RETURN, 0, {L'\r'}, 0}},
};
int main( int, char*[] )
{
printf("\n(type 'exit' to exit the subshell)\n");
// start a command interpreter asynchronously
intptr_t process_handle = _spawnlp(_P_NOWAIT, "cmd", "/k", "prompt", "SUBSHELL: ", NULL);
// get own console handle
HANDLE con_input_handle = GetStdHandle(STD_INPUT_HANDLE);
// send input to the console
DWORD n_written;
WriteConsoleInputW(con_input_handle, SimulatedInput, _countof(SimulatedInput), &n_written);
// wait for child process to exit
_cwait(NULL, process_handle, 0);
return 0;
}
上面的示例必须编译为控制台程序,因为它使用GetStdHandle
来获取控制台输入句柄。当父级是控制台应用程序时,子控制台应用程序将与父级共享控制台。如果parent是一个GUI应用程序,因此没有控制台,请在调用GetStdHandle
之前使用AttachConsole函数附加到子进程控制台,然后在完成后调用FreeConsole。
答案 1 :(得分:0)
VOID WriteToPipe(VOID)
{
DWORD dwWritten;
CHAR chBuf[3];
sprintf(chBuf,"y\r\n");
if(logLevel==1)
log("trying to write y to child\n",1);
// Read from a file and write its contents to a pipe.
if (! WriteFile(hChildStdinWr, chBuf, 3,
&dwWritten, NULL))
if(logLevel ==1)
log("cannot write to child in write\n",1);
// Close the pipe handle so the child process stops reading.
/*
if (! CloseHandle(hChildStdinWr)) {
if(logLevel==1)
log("Close pipe failed in write \n");
ExitProcess(0);
}
*/
}
void ReadFromPipe(VOID)
{
DWORD dwRead, dwWritten;
CHAR chBuf[MAX];
// Close the write end of the pipe before reading from the
// read end of the pipe.
log("reading data from child process \n",1 );
/*if (!CloseHandle(hChildStdoutWr)) {
cerr<<"Closing handle failed\n";
ExitProcess(0);
}*/
// Read output from the child process, and write to parent's STDOUT.
for(;;)
{
if( !ReadFile( hChildStdoutRd, chBuf, MAX, &dwRead,
NULL) || dwRead == 0) break;
if (! WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL))
break;
if(logLevel ==1) {
log(chBuf,1);
log("\n");
}
memset(chBuf,NULL,MAX);
}
log("finished reading \n",1);
}
BOOL CreateChildProcess()
{
TCHAR szCmdline[1024] ;
if(pool && !submit) {
sprintf(szCmdline,"program.exe");
}
else {
sprintf(szCmdline,"command.exe argument");
}
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bFuncRetn = FALSE;
// Set up members of the PROCESS_INFORMATION structure.
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
// Set up members of the STARTUPINFO structure.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = hChildStdoutWr;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
// Create the child process.
bFuncRetn = CreateProcess(NULL,
szCmdline, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if (bFuncRetn == 0) {
ExitProcess(0);
}
return bFuncRetn;
}
void execute() {
SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess;
// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
// Get the handle to the current STDOUT.
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
// Create a pipe for the child process's STDOUT.
if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) {
ExitProcess(1);
}
// Ensure that the read handle to the child process's pipe for STDOUT is not
inherited.
SetHandleInformation( hChildStdoutRd, HANDLE_FLAG_INHERIT, 0);
// Create a pipe for the child process's STDIN.
if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) {
ExitProcess(1);
}
// Ensure that the write handle to the child process's pipe for STDIN is not
nherited.
SetHandleInformation( hChildStdinWr, HANDLE_FLAG_INHERIT, 0);
// Now create the child process.
fSuccess = CreateChildProcess(host,password,action,username);
if (! fSuccess) {
cerr<<"Create process failed";
ExitProcess(0);
}
CloseHandle(hChildStdinRd);
CloseHandle(hChildStdoutWr);
WriteToPipe();
ReadFromPipe();
}