当程序有大量输出时,挂起cmd.exe的CreateProcess

当程序有大量输出时,挂起cmd.exe的CreateProcess,c,windows,winapi,cmd,process,C,Windows,Winapi,Cmd,Process,我正在使用CreateProcess通过自定义命令调用cmd.exe: #包括 #包括 int main(){ 句柄stdout_w=NULL; 句柄stdout\u r=NULL; 安全属性sattr={0}; sattr.nLength=sizeof(安全属性); sattr.bInheritHandle=TRUE; 如果(!CreatePipe(&stdout\u r,&stdout\u w,&sattr,0)) 返回退出失败; SetHandleInformation(标准输出,句柄标志

我正在使用
CreateProcess
通过自定义命令调用
cmd.exe

#包括
#包括
int main(){
句柄stdout_w=NULL;
句柄stdout\u r=NULL;
安全属性sattr={0};
sattr.nLength=sizeof(安全属性);
sattr.bInheritHandle=TRUE;
如果(!CreatePipe(&stdout\u r,&stdout\u w,&sattr,0))
返回退出失败;
SetHandleInformation(标准输出,句柄标志,0);
进程信息pi={0};
StartupInfoaSI={0};
si.cb=sizeof(si);
si.hStdError=stdout\u w;
si.hst输出=标准输出w;
si.dwFlags=STARTF_USESTDHANDLES;
char命令[256];
strcpy(命令,countof(命令),“cmd/s/C\”ag\“ch\”);
if(!CreateProcessA(NULL,command,NULL,NULL,TRUE,0,NULL,“c:/users/lisa/projects/monkey”、&si和&pi))
返回退出失败;
while(true){
开关(WaitForSingleObject(pi.hProcess,0)){
案例等待超时:
打破
案例等待对象0:
返回退出成功;
违约:
返回退出失败;
}
}
}
在这里,我用命令
ag“ch”
调用
cmd.exe
。(
ag
是一个搜索文件中字符串的实用程序,类似于
grep

问题是,它挂起了——最后的循环永远运行,我可以看到创建的
cmd.exe
进程在任务管理器中保持打开状态。关于这件事有几件奇怪的事:

  • 当我直接从命令提示符运行
    cmd.exe/S/C“ag”ch”“
    时,它工作正常并按预期退出
  • 当我将代码更改为运行
    ag“chi”
    (即搜索更大的子字符串)时,它将按预期退出。此外,当我将目录更改为没有任何文件的文件夹时,它也会按预期退出。这使我认为问题在于
    ag
    的输出太长
  • 当我直接将
    ag“ch”
    命令传递给
    CreateProcess
    时,它会按预期退出。(不幸的是,我不能这样做,因为这是一个更大的实用程序的一部分,它允许我从C运行任何批处理命令,包括使用管道。)

有人知道这里发生了什么吗?

我希望您的命令文本字符串是
“cmd/s/C ag\”ch\\\
,而不是
“cmd/s/C\”ag\”ch\\\\\\\
。在我看来,太多的双引号导致命令行为
cmd/S/C“ag”ch”“
,而您需要的是
cmd/S/C ag“ch”
。为什么要运行cmd而不是direct ag.exe?在哪里使用重定向输出?你为什么要重定向它?您不需要对管道进行任何读写操作此代码从一个更大的实用程序类中剥离出来,该类允许我调用任何批处理命令(例如,
ag ch|filter
)并读取输出。此代码只是为了演示问题。管道已满,因此程序无法向其中写入更多数据。您必须从管道中读取已写入的数据,才能为更多数据腾出空间。为什么要在0毫秒超时的紧循环中调用
WaitForSingleObject()
?完全摆脱这种轮询循环,只需调用
WaitForSingleObject()
一次,然后使用
INFINITE
超时。