WINDOWS 管道编程

本文介绍了一个具体的Windows环境下管道通信实现案例。通过创建匿名管道,并利用CreateProcess函数来启动子进程,实现了父进程与子进程之间的双向通信。文章详细展示了如何重定向子进程的标准输入和输出到管道中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

因为工作的要求,要做一个格式化程序,找了很多资料,发现管道的代码都差不多,一气之下,自己写了个

 

    //pipe attribute
    SECURITY_ATTRIBUTES         sa; 
       sa.bInheritHandle         
= TRUE;   
    sa.nLength                
= sizeof(SECURITY_ATTRIBUTES);  //使用系统默认的安全描述符  
    sa.lpSecurityDescriptor   = NULL;   //一定要为TRUE,不然句柄不能被继承
    
    
//Read Info from process
    
//SubProcess->MainProcess 
    
//SubProcess  write something to   output.
    
//                                   |
    
//MainProcess read  something from input. 
    
//so
    
//SubPorcess Redirect STDOUT to WritePipe handler
    
//hWrite0 can only be used by SubProcess.
    
//so push hWrite0 as a parameter of CreateProcess
    
//and after CreateProcess,should Close hWrite0.
    HANDLE                       hRead0,hWrite0;
    HANDLE                       hReadPipeNonInheritable;
    
//get STDOUT handler
    HANDLE hStdout =::GetStdHandle(STD_OUTPUT_HANDLE);
    
if( hStdout == INVALID_HANDLE_VALUE )
    
{
        ::MessageBox(NULL, TEXT(
"Can not retrieve stdout"), TEXT("Error"), MB_OK);
        
return;
    }

    
if(!CreatePipe(&hRead0,&hWrite0,&sa,0)) //创建匿名管道    
    {   
        
return;   
    }
  
    
//redirect to STDOUT to WritePipe handler.
    if!::SetStdHandle(STD_OUTPUT_HANDLE, hWrite0) )
    
{
        ::MessageBox(NULL, TEXT(
"Can not redirect stdout"), TEXT("Error"), MB_OK);
        ::CloseHandle( hRead0);
        ::CloseHandle( hWrite0);
        
return;
    }

    
//duplicatehandle get hReadPipeNonInheritable ,which is inheritable.
    if( ::DuplicateHandle(
        GetCurrentProcess(), hRead0,
        GetCurrentProcess(), 
&hReadPipeNonInheritable,
        
0, FALSE, DUPLICATE_SAME_ACCESS))
    
{
        ::CloseHandle( hRead0);
        hRead0 
= NULL;
    }

    
else
    
{
        ::MessageBox(NULL, TEXT(
"Can not duplicate handle"), TEXT("Error"), MB_OK);
        ::CloseHandle( hRead0 );
        ::CloseHandle( hWrite0 );
        ::SetStdHandle(STD_OUTPUT_HANDLE, hStdout);
        
return ;
    }


    
//write info to  SubProcess
    
//MainProcess->SubProcess 
    
// MainProcess write something to   output.----||
    
//                                             ||PIPE 
    
//SubProcess   read  something from input. <---||
    
//so
    
//SubPorcess Redirect STDINPUT to ReadPipe handler
    
//hRead1 can only be used by SubProcess.
    
//so push hRead1 as a parameter of CreateProcess
    
//and after CreateProcess,should Close hRead1.
    HANDLE hRead1,hWrite1; 
    HANDLE hWritePipeNonInheritable;
    HANDLE hStdin 
=::GetStdHandle( STD_INPUT_HANDLE );
    
if( hStdin == INVALID_HANDLE_VALUE )
    
{
        ::MessageBox(NULL, TEXT(
"Can not retrieve stdin"), TEXT("Error"), MB_OK);
        
return;
    }

    
if(!CreatePipe(&hRead1,&hWrite1,&sa,0)) //创建匿名管道    
    {   
        
return;   
    }
 
    
if!::SetStdHandle(STD_INPUT_HANDLE, hRead1) )
    
{
        ::MessageBox(NULL,TEXT(
"Can not redirect stdin"), TEXT("Error"), MB_OK);
        ::CloseHandle( hRead1);
        ::CloseHandle( hWrite1);
        
return;
    }
    
    
if( ::DuplicateHandle(
        GetCurrentProcess(), hWrite1,
        GetCurrentProcess(), 
&hWritePipeNonInheritable,
        
0, FALSE, DUPLICATE_SAME_ACCESS ) )
    
{
        ::CloseHandle(hWrite1);
        hWrite1 
= NULL;
    }

    
else
    
{
        ::MessageBox(NULL, TEXT(
"Can not duplicate handle"), TEXT("Error"), MB_OK);
        ::CloseHandle( hRead1 );
        ::CloseHandle( hWrite1 );
        ::SetStdHandle(STD_INPUT_HANDLE, hStdin);
        
return  ;
    }

    
    STARTUPINFO           si;  
// 启动信息  
    PROCESS_INFORMATION   pi;    // 进程信息 
    si.cb                 =   sizeof(STARTUPINFO);   
    GetStartupInfo(
&si);     //取得当前进程的StartupInfo,并根据当前进程进行修改
    si.hStdError     =   hWrite0;    //错误输出 表示为子进程的输出
    si.hStdOutput    =   hWrite0;   //标准输出
    si.hStdInput     =   hRead1;
    si.wShowWindow   
=   SW_HIDE; 
    si.dwFlags       
=   STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;   
    
//创建子进程
    if(!CreateProcess(NULL,"cmd.exe",NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi))     
    
{   
        
return   /*FALSE*/;   
    }
   
    CloseHandle(hWrite0); 
//关闭主进程的输出。
    CloseHandle(hRead1);
    
    
// restore stdin
    if!::SetStdHandle(STD_INPUT_HANDLE, hStdin) )
    
{
        ::MessageBox(NULL, TEXT(
"Can not restore stdin"), TEXT("Error"), MB_OK);
        ::CloseHandle( hWritePipeNonInheritable );
        
return ;
    }

    
if!::SetStdHandle(STD_OUTPUT_HANDLE, hStdout) )
    
{
        ::MessageBox(NULL, TEXT(
"Can not restore stdout"), TEXT("Error"), MB_OK);
        ::CloseHandle( hReadPipeNonInheritable );
        
return ;
    }


    
char  CMD[512]="ping www.163.com "
    
char   buffer[4096]={0};   
    DWORD   bytesRead;     
    WriteFile(hWritePipeNonInheritable,CMD,strlen(CMD),
&bytesRead,NULL);
    CString tmp;
    
while (true)     
    
{   
        
if(ReadFile(hReadPipeNonInheritable,buffer,4095,&bytesRead,NULL)==NULL)   
        
{
            
break;
        }

        TRACE(buffer);
        tmp
+=buffer;
        m_edit1.SetWindowText(tmp);
        m_edit1.LineScroll(m_edit1.GetLineCount()); 
        Sleep(
200);     
    }
 
    

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值