我正在使用 CreateProcess
启动一个交互式脚本解释器,并希望透明地将stdin / stdout / stderr转发给解释器 .
我的第一次尝试是设置传递给 CreateProcess
的 STARTUPINFO
结构
STARTUPINFOA si = { sizeof( si ) };
si.hStdError = ::GetStdHandle( STD_ERROR_HANDLE );
si.hStdOutput = ::GetStdHandle( STD_OUTPUT_HANDLE );
si.hStdInput = ::GetStdHandle( STD_INPUT_HANDLE );
si.dwFlags |= STARTF_USESTDHANDLES;
即我试图使脚本解释器进程使用与我的启动程序进程使用的读/写相同的句柄 . 这似乎不起作用(我甚至不确定那些标准句柄是否可以继承) .
基于Creating a Child Process with Redirected Input and Output示例的第二个想法是设置三个管道以转发写入任何管道的所有数据 . 由于我不知道如何等待数据写入多个文件( WaitForMultipleObjects
无法在管道上同步),我正在考虑有三个线程,每个线程在管道上执行阻塞 ReadFile
调用 .
我怀疑这可能有点矫枉过正,所以我想知道:有更简单的方法吗?我根本不需要对从脚本解释器传递的数据进行任何处理 .
作为旁注,在Linux上我使用 execvp
只是用脚本解释器进程替换当前进程,但在Windows上我需要启动脚本解释器,主线程处于挂起状态(这样我就可以进行一些字节码修补) - 所以即使自_execvp似乎可以在Windows上使用,我显然必须使用CreateProcess .
2 回答
为了等待多个文件或管道上的I / O,您需要对每个文件发出异步I / O请求,然后等待所述请求的完成 . 沿着这些方向的东西(未经测试):
需要在循环中调用
ReadFile
和WaitForMultipleObjects
. 检查WaitForMultipleObjects
的返回值以了解哪个操作已完成,使用GetOverlappedResult
来发现该操作的结果(是否成功,如果是,它检索了多少字节),处理数据,再次调用该句柄的ReadFile
如果你想从中读更多,然后回到等待 . 这有点类似于Linux中由select
驱动的非阻塞I / O循环 .更先进的技术是I/O completion ports . 这允许一个线程池处理大量异步I / O.常用于Web服务器等,可能对您的情况有些过分 .
如果确保不在CreateProcess的
dwFlags
参数中传递CREATE_NO_WINDOW
参数,那么如OP所示PopuplatingSTARTUPINFO
就可以正常工作 .