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

0x01.CreatePipe

管 道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另 一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。

BOOL WINAPI CreatePipe(
  _Out_    PHANDLE               hReadPipe,
  _Out_    PHANDLE               hWritePipe,
  _In_opt_ LPSECURITY_ATTRIBUTES lpPipeAttributes,
  _In_     DWORD                 nSize
);

0x02.CreateProcess

BOOL WINAPI CreateProcess(
  _In_opt_    LPCTSTR               lpApplicationName,
  _Inout_opt_ LPTSTR                lpCommandLine,
  _In_opt_    LPSECURITY_ATTRIBUTES lpProcessAttributes,
  _In_opt_    LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_        BOOL                  bInheritHandles,
  _In_        DWORD                 dwCreationFlags,
  _In_opt_    LPVOID                lpEnvironment,
  _In_opt_    LPCTSTR               lpCurrentDirectory,
  _In_        LPSTARTUPINFO         lpStartupInfo,
  _Out_       LPPROCESS_INFORMATION lpProcessInformation
);

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

方法一:创建一个pipe然后是cmd执行的结果输出到pipe里,然后再读取,这里遇到一个问题就是在hInput 这个witepipe写完之后得关闭,使write 结束,这样之后的readfile才可以执行而不被阻塞;

int ReadCmdContextOne()
{
  STARTUPINFO st ;
  PROCESS_INFORMATION pi;
  HANDLE hOutPut,hInPut;
  SECURITY_ATTRIBUTES sa;
  DWORD readByte = 0;
  int len = 0;
  BOOL hResult ;
  char buffer[4096];

  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  sa.bInheritHandle =TRUE;
  sa.lpSecurityDescriptor = NULL;

  if(!CreatePipe(&hOutPut,&hInPut,&sa,0))
  {
    cout<<"create pipe failed erorr="<return 1;
  }

  st.cb = sizeof(STARTUPINFO);
  GetStartupInfo(&st);
  st.hStdOutput = hInPut;
  st.hStdError = hInPut;
  st.wShowWindow = SW_HIDE;
  st.dwFlags = STARTF_USESHOWWINDOW |STARTF_USESTDHANDLES;

  if(!CreateProcess(NULL,"c:\\windows\\system32\\cmd.exe /c ipconfig /all",NULL,
  NULL,TRUE,NULL,NULL,NULL,&st,&pi))
  {
    cout<<"failed create proccess,error="<return 1;
  }

  DWORD dwRet = WaitForSingleObject(pi.hProcess,INFINITE);
  switch(dwRet)
  {
    case WAIT_TIMEOUT:
    case WAIT_FAILED:
      return 1;
    case WAIT_OBJECT_0:
    CloseHandle(hInPut);//close hInPut handle ,make hte write pipe completes
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
  }

  memset(buffer,0,sizeof(buffer));
  do
  {  
    //a write operation completes on the write end of the pipe,so ReadFile can begin
    hResult = ReadFile(hOutPut,buffer+len,1024,&readByte,NULL);
    len += readByte;
    Sleep(200);
  }
  while(readByte!=0 && hResult);

  cout<return 0;
}

方法二:
就是执行命令的时候加一个输出重定向到文件,然后再从文件中读取;文件最好建一个临时文件,不过windows还是不会帮我们自动删除的,需要我们自己删除;

void exec()
{
  HANDLE hFile;
  STARTUPINFO st = {sizeof(STARTUPINFO)} ;
  PROCESS_INFORMATION pi;
  char szTempPath[MAX_PATH];
  char szTempFile[MAX_PATH];
  char buffer[4096];
  char cmdLine[100];
  DWORD dwRet ;
  DWORD dwReadByte;

  dwRet = GetTempPath(MAX_PATH,szTempPath);
  if(!SUCCEEDED(dwRet))
  {
    cout<<"failed to Get temp path"<return 1;
  }

  dwRet = GetTempFileName(szTempPath,TEXT("JJJJJay.txt"),0,szTempFile);
  if(!SUCCEEDED(dwRet))
  {
    cout<<"failed to create temp file"<return 1;
  }

  memset(cmdLine,0,sizeof(cmdLine));
  int strLen = sizeof("c:\\windows\\system32\\cmd.exe /c ipconfig /all >");
  memcpy(cmdLine,"c:\\windows\\system32\\cmd.exe /c ipconfig /all >",strLen);
  memcpy(cmdLine+strLen-1,szTempFile,sizeof(szTempFile));
  cmdLine[strLen+sizeof(szTempFile)] = '\0';
  cout<if(!CreateProcess(NULL,cmdLine,NULL,
  NULL,TRUE,NULL,NULL,NULL,&st,&pi))
  {
    cout<<"failed create proccess,error="<return 1;
  }

  dwRet = WaitForSingleObject(pi.hProcess,INFINITE);
  switch(dwRet)
  {
    case WAIT_TIMEOUT:
    case WAIT_FAILED:
      return 1;
    case WAIT_OBJECT_0:
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
  }

  hFile = CreateFile(szTempFile,GENERIC_READ,FILE_SHARE_DELETE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
  if(hFile == INVALID_HANDLE_VALUE)
  {
    cout<<"failed to create file"<return 0;
  }

  memset(buffer,0,sizeof(buffer));
  int len = 0 ;
  do
  {
    dwRet = ReadFile(hFile,buffer+len,1024,&dwReadByte,NULL);
    len += dwRet;
  }while(dwRet && dwReadByte!=0);

  CloseHandle(hFile);
  DeleteFile(szTempFile);

  return 0;
}

你可能感兴趣的:(windows之API函数,winapi,计算机,通信)