Rover12421's Blog

The End.

管道piep使用ReadFile读取阻塞问题解决

        最近用VS2012在写一个Android ADB操作的程序,遇到一个挺头疼的问题,从管道pipe中读取“adb start-server”结果,总是被阻塞,无法正常结束流程。查找了很多资料,总算是解决了。原来管道pipe是可以通过PeekNamedPipe预览其中的数据的,然后再配合WaitForSingleObject判断进程是否完成,顺利解决问题。

        完整的控制台程序如下:

// Exec.cpp : Defines the entry point for the console application.// By Rover12421// 2013/09/24 #include "stdafx.h"

#include #include #include

usingnamespacestd;

intreadPipe(HANDLEhRead,CString&readStr)
{   for   {       DWORDdwAvail=;
       if!PeekNamedPipe(hRead,nullptr,,nullptr,&dwAvail,nullptr))
       {           break;
       }

       ifdwAvail<=)
       {           return1;
       }

       charszOutput[4096];       ZeroMemory(&szOutput,sizeof(szOutput));
       DWORDdwRead=;
       if!ReadFile(hRead,szOutput,min(4095,dwAvail),&dwRead,nullptr) || !dwRead)
       {           break;
       }

       readStr+=szOutput;
   }

   DWORDdwError=GetLastError();
   ifdwError==ERROR_BROKEN_PIPE       || dwError==ERROR_NO_DATA)
   {       return;
   }

   readStr.Append(_T("Read stdout pipe error\r\n"));
   return-1;
}

CStringexecCMD(CStringcmd)
{   SECURITY_ATTRIBUTESsa;
   ZeroMemory( &sa,sizeof(sa) );

   HANDLEhRead,hWrite;

   sa.nLength=sizeof(SECURITY_ATTRIBUTES);
   sa.lpSecurityDescriptor=nullptr;
   sa.bInheritHandle=TRUE;
   if!CreatePipe(&hRead,&hWrite,&sa,))
   {       return_T("err 执行命令失败");
   }

   STARTUPINFOsi;
   ZeroMemory( &si,sizeof(si) );
   si.cb=sizeof(si);
   PROCESS_INFORMATIONpi;
   ZeroMemory( &pi,sizeof(pi) );

   GetStartupInfo(&si);
   si.hStdError=hWrite;
   si.hStdOutput=hWrite;
   si.wShowWindow=SW_HIDE;
   si.dwFlags=STARTF_USESHOWWINDOWSTARTF_USESTDHANDLES;

   booleanbRet=CreateProcess(nullptr,cmd.GetBuffer(),nullptr,nullptr,TRUE,CREATE_NEW_CONSOLE,nullptr,nullptr,&si,&pi);
   cmd.ReleaseBuffer();
   if!bRet)
   {       CloseHandle(hRead);
       CloseHandle(hWrite);
       return  _T("err 执行命令失败");
   }

   CStringstr;
       
   intnRet;
   for   {       nRet=readPipe(hRead,str);
       ifnRet<=)
       {           break;
       }

       DWORDdwRc=WaitForSingleObject(pi.hProcess,100);
       ifdwRc==WAIT_OBJECT_0)
       {           //the child process ended           nRet=readPipe(hRead,str);
           ifnRet>)
           {               nRet=;
           }           break;
       }   }

   CloseHandle(pi.hThread);
   CloseHandle(pi.hProcess);

   CloseHandle(hWrite);
   CloseHandle(hRead);
   returnstr;
}

int_tmain(intargc,_TCHAR*argv[]){   setlocale(LC_ALL,"chs");

   CStringret=execCMD(_T("adb start-server"));
   wcout<<ret.GetBuffer() <<endl;
   ret.ReleaseBuffer();
   return;
}

Comments