关于管道向命令行输入输出失败有关问题
关于管道向命令行输入输出失败问题
情景:我要实现的目的是通过我的程序,取得本地的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赋值为1 varWrite = 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); }
- 1楼eagleatustb昨天 10:41
- 问题找到了,是因为输入命令没有加回车键表示结束输入;n50. memset(recv_buff,'\0',1024); n51. memcpy(recv_buff,"dir",3); n这里需要在dir后面加上回车