关于管道向命令行输入输出失败问题
情景:我要实现的目的是通过我的程序,取得本地的CMD的命令输入入口和输出。即我输入任何CMD命令,能通过CMD窗口(隐藏的)来执行,并把结果输出到我指定的地方。
实现方法:主线程M先创建两个子线程A和B。
线程A负责产生输入管道PA,并把从其他方式送过来的命令写到这个管道PA(通过在创建CMD进程时指定startinfo.hStdInput来指定监听的输入);
线程B负责产生输出管道PB,并监听管道PB数据写到指定目的地。
主线程等A,B线程产生好管道以后,创建CMD的进程,在参数中把startinfo.hStdInput设置为读PA数据,startinfo.hStdOutput设置为输出到PB。情景如下图:
问题描述,线程A正常运行,线程B也正常运行,主线程创建CMD进程成功,其设置输入输入参数也是在管道产生之后的正确参数。问题是:我可以正常在线程A把命令数据(如dir)写到管道PA中(WriteFile返回TRUE),但无法在线程B中监听到处理结果。
我觉得上图两个问号就是可能出现问题的地方。但目前没有办法确认,下面附上代码。请问有哪位处理过相关问题的,麻烦指导一下。谢谢!
#include <stdio.h>#include <string.h>#include <winsock2.h>HANDLE hReadPipe, hWritePipe, hWriteFile, hReadFile;u_char varRead,varWrite;DWORD WINAPI ThreadFuncRead(LPVOID lpParam){ //声明一个安全属性结构变量 SECURITY_ATTRIBUTES pipeattr; DWORD nByteToWrite, nByteWritten; char recv_buff[1024];int nRetCode;//对pipeattr的各个成员进行赋值memset(recv_buff,0,sizeof(recv_buff)); pipeattr.nLength = sizeof(SECURITY_ATTRIBUTES); pipeattr.lpSecurityDescriptor = NULL;pipeattr.bInheritHandle = TRUE;//创建一个匿名管道,并使用上面的安全属性结构变量pipeattr为管道的安全属性//其中hReadPipe是用来从管道中读取数据的管道句柄//hWriteFile是向管道写入数据的管道句柄 nRetCode = CreatePipe(&hReadPipe,&hWriteFile,&pipeattr,0); //判断管道是否创建成功 if (nRetCode == 0) { printf ("CreatePipe readpipe Error!\n"); exit(-1);}//如果管道创建成功,就将varRead赋值为1 varRead = 1;//得到当前进程的路径,当有用户连接上时就会显示出来TCHAR curDirBuff[256];memset(curDirBuff,0,sizeof(curDirBuff));DWORD nDirLength=0;nDirLength = GetCurrentDirectory(256,curDirBuff);curDirBuff[nDirLength]='>';nRetCode=WriteFile(hWriteFile,curDirBuff,nDirLength+1,&nDirLength,NULL);//使用一个无限循环,来从客户端接收数据,并写入管道 while(true) { Sleep(250); //从客户端接收数据,数据写入缓冲区recv_buff中memset(recv_buff,'\0',1024);memcpy(recv_buff,"dir",3);nByteToWrite = strlen(recv_buff); //使用WriteFile向句柄hWriteFile中写入数据,这个管道中的数据可以通过 //hReadFile管道句柄读取,而hReadFile是全局变量,则在程序中的任何地方 //都可以访问到 nRetCode = WriteFile(hWriteFile,recv_buff,nByteToWrite,&nByteWritten,NULL); } return 0;}DWORD WINAPI ThreadFuncWrite( LPVOID lpParam ){ //同样是先来声明一个安全属性变量pipeattr SECURITY_ATTRIBUTES pipeattr; DWORD len; int nRetCode; unsigned long nCount; unsigned long nAvail; char send_buff[25000]; ZeroMemory(send_buff, 25000); //对安全属性变量赋初值 pipeattr.nLength = sizeof(SECURITY_ATTRIBUTES); pipeattr.lpSecurityDescriptor = NULL; pipeattr.bInheritHandle = TRUE; //创建另外一个匿名管道,其使用的参数与上面一个线程函数处相同 nRetCode = CreatePipe(&hReadFile,&hWritePipe,&pipeattr,0); //如果管道创建失败,就返回 if (nRetCode == 0) { printf ("CreatePipe writepipe Error!\n"); exit(-1);}//管道创建成功,将varWrite赋值为1varWrite = 1;//进入一个无限循环,每隔250ms就尝试从上面的这个匿名管道中读取数据,如果//管道中存在数据,ReadFile()函数通过hReadFile就可以读到数据,而且当且仅//当读到了数据,服务端才会向客户端发送数据。 while (true) { Sleep(250); //尝试从hReadFile中读取数据,数据长度放入len ReadFile(hReadFile,send_buff,25000,&len,NULL);printf("%s",send_buff); } return 0;}int _tmain(int argc, _TCHAR* argv[]){varRead = 0;varWrite = 0;DWORD dwThreadRead;HANDLE hThreadFuncRead = 0;if((hThreadFuncRead = CreateThread(NULL,0,ThreadFuncRead,NULL,0,&dwThreadRead)) == NULL){printf("create ThreadFuncRead error!\n");return 0;}if(CreateThread(NULL,0,ThreadFuncWrite,NULL,0,&dwThreadRead) == NULL){printf("create ThreadFuncWrite Error!\n");return 0;}do{Sleep(250);}while((!varRead || !varWrite));PROCESS_INFORMATION processinfo;STARTUPINFO startinfo;GetStartupInfo(&startinfo);startinfo.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;startinfo.lpDesktop = NULL;startinfo.hStdInput = hReadPipe;startinfo.hStdOutput = hWritePipe;startinfo.hStdError = hWritePipe;startinfo.wShowWindow = SW_SHOWNORMAL;TCHAR DirSys[256];::GetSystemDirectory(DirSys,256);wcscat(DirSys,_T("\\cmd.exe"));if(!CreateProcess(DirSys,NULL,NULL,NULL,TRUE,0,NULL,NULL,&startinfo,&processinfo)){printf("CreateProcess Error!\n");return 0;}WaitForSingleObject(hThreadFuncRead,INFINITE);}