使用MFC创建匿名管道时出现一些问题,我是按照孙鑫老师的VC++深入详解的第17课的例子里面的步骤写的
代码和书上的完全一样,没有哦发现有什么不同的地方
但是第一次创建管道的时候在建立子进程时,子进程无法获取父进程的读写管道的句柄,但是当我再次创建管道时,子进程能够读取父进程的低些句柄,但是读取到的却是第一次创建管道时父进程的读写句柄,即以后每次创建一个子进程,他获得的都是上一个父进程的读写句柄,而不是本次所重新创建的管道的读写句柄。
不知道这是为什么?书上的步骤是这样的:
对于父进程:
1、创建匿名管道
2、创建子进程
3、编写写入数据到管道的代码;
4、编写从管道读取数据的代码;对于子进程:
1、在建立窗口的时候获取父进程的读写句柄
2、编写相关到写入数据的代码;
3、编写从管道读取数据的代码;
对应的代码如下:父进程步骤1和2代码
void CParentView::OnPipeCreate() 
{
// TODO: Add your command handler code here
SECURITY_ATTRIBUTES sa;
sa.bInheritHandle=true;
sa.lpSecurityDescriptor=NULL;
sa.nLength=sizeof(SECURITY_ATTRIBUTES); STARTUPINFO sui;
PROCESS_INFORMATION pi;

ZeroMemory(&sui,sizeof(STARTUPINFO));
sui.cb=sizeof(STARTUPINFO);
sui.dwFlags=STARTF_USESTDHANDLES;
sui.hStdInput=hRead;
sui.hStdOutput=hWrite;
sui.hStdError=GetStdHandle(STD_ERROR_HANDLE);
if(!CreatePipe(&hRead,&hWrite,&sa,0))
{
//CloseHandle(hRead);
//CloseHandle(hWrite);
AfxMessageBox("管道创建失败!");
return;
}

CString str1,str2;
str1.Format("hRead=%d",hRead);
str2.Format("hWrite=%d",hWrite);
AfxMessageBox(str1);
AfxMessageBox(str2); if(!CreateProcess("..\\Child\\Debug\\Child.exe",NULL,NULL,NULL,true,0,NULL,NULL,&sui,&pi))
{
CloseHandle(hRead);
CloseHandle(hWrite);
hRead=NULL;//防止在析构函数中再次调用CloseHandle
hWrite=NULL;
AfxMessageBox("进程创建失败!");
return;
}
else
{
CloseHandle(pi.hProcess);//在这里关闭
CloseHandle(pi.hThread);
}
}父进程步骤3代码
void CParentView::OnPipeWrite() 
{
// TODO: Add your command handler code here
char buf[]="父类数据!";
DWORD dwWrite; if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
AfxMessageBox("写入管道失败!");
return;
}
}
父进程步骤4代码
void CParentView::OnPipeRead() 
{
// TODO: Add your command handler code here
char buf[100];
DWORD dwRead; if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
AfxMessageBox("读取管道失败!");
return;
} AfxMessageBox(buf);
}子进程代码:
子进程步骤1代码void CChildView::OnInitialUpdate() 
{
CView::OnInitialUpdate();

// TODO: Add your specialized code here and/or call the base class
hRead=GetStdHandle(STD_INPUT_HANDLE);
hWrite=GetStdHandle(STD_OUTPUT_HANDLE); if(INVALID_HANDLE_VALUE ==hRead)
AfxMessageBox("hRead获取失败!");
if(INVALID_HANDLE_VALUE ==hWrite)
AfxMessageBox("hWrite获取失败!"); CString str1,str2;
str1.Format("child hRead=%d",hRead);
str2.Format("Child hWrite=%d",hWrite);
AfxMessageBox(str1);
AfxMessageBox(str2);
}
子进程步骤2代码void CChildView::OnPipeWrite() 
{
// TODO: Add your command handler code here
char buf[]="child write pipe";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
AfxMessageBox("管道写入失败!");
return;
}}
子进程步骤3代码void CChildView::OnPipeRead() 
{
// TODO: Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
AfxMessageBox("读取管道失败!");
return;
}
AfxMessageBox(buf);
}

解决方案 »

  1.   

    从我自己的调试结果看是在子进程的OnInitialUpdate()中执行GetStdHandle(STD_INPUT_HANDLE)时没能获取需要的句柄,在第二次启动子进程时才能获取上一次的句柄,我比较菜,没有找到原因
      

  2.   

    发现问题了,之所以出现上面的情况是应为在给STARTUPINFO sui这个变量赋值时由于还没有条用CreatePipe()来创建管道,故没有获取需要的hRead和hWrite的值(由于在构造函数中赋值为NULL)从而sui.hStdInput=hRead和sui.hStdOutput=hWrite时他们都为零,直到下次调用时才会取得这次的句柄值。应该将以下代码写在CreatePipe()之后:
    sui.cb=sizeof(STARTUPINFO);
    sui.dwFlags=STARTF_USESTDHANDLES;
    sui.hStdInput=hRead;
    sui.hStdOutput=hWrite;
    sui.hStdError=GetStdHandle(STD_ERROR_HANDLE);