关于管道向命令行输入输出失败有关问题

关于管道向命令行输入输出失败问题

情景:我要实现的目的是通过我的程序,取得本地的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后面加上回车