win32 确保从子进程正确读取所有数据

发布于 2025-01-09 09:42:41 字数 2249 浏览 0 评论 0原文

我想使用 WIN32 API CreateProcess 从另一个 C++ 应用程序启动一个控制台 C++ 应用程序。该子控制台应用程序返回一些结果,我想读取父应用程序中子进程的结果。这是我的代码。

void executeCommand(const std::string& lpCommandLine) 
{
  PROCESS_INFORMATION processInfo;
  STARTUPINFOA startupInfo;
  SECURITY_ATTRIBUTES saAttr;

  HANDLE stdoutReadHandle  = NULL;
  HANDLE stdoutWriteHandle = NULL;

  std::string outbuf;
  DWORD bytes_read;
  char tBuf[257];
  DWORD exitcode;
  BOOL bSuccess = FALSE;

  memset(&saAttr, 0, sizeof(saAttr));
  saAttr.nLength              = sizeof(SECURITY_ATTRIBUTES);
  saAttr.bInheritHandle       = TRUE;
  saAttr.lpSecurityDescriptor = NULL;



 // Create a pipe for the child process's STDOUT.
  if (!CreatePipe(&stdoutReadHandle, &stdoutWriteHandle, &saAttr, 5000))
  {
    return;
  }

  // Ensure the read handle to the pipe for STDOUT is not inherited.
  if (!SetHandleInformation(stdoutReadHandle, HANDLE_FLAG_INHERIT, 0))
  {
    return;
  }

  memset(&startupInfo, 0, sizeof(startupInfo));
  startupInfo.cb          = sizeof(startupInfo);
  startupInfo.hStdError   = stdoutWriteHandle;
  startupInfo.hStdOutput  = stdoutWriteHandle;
  startupInfo.wShowWindow = SW_HIDE;
  startupInfo.hStdInput   = GetStdHandle(STD_INPUT_HANDLE);
  startupInfo.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;

  if (!CreateProcessA(NULL, (LPSTR)lpCommandLine.c_str(), NULL, NULL, TRUE, CREATE_NEW_CONSOLE,
                      NULL,
                      0, &startupInfo,
                      &processInfo))
  {
    return;
  }

  CloseHandle(stdoutWriteHandle);

  for (;;)
  {
    bSuccess = ReadFile(stdoutReadHandle, tBuf, 256, &bytes_read, NULL);

    if (!bSuccess || bytes_read == 0)
    {
      break;
    }
    if (bytes_read > 0)
    {
      tBuf[bytes_read] = '\0';
      outbuf += tBuf;
    }
  }

  cmdOutput_ = outbuf;

  if (WaitForSingleObject(processInfo.hProcess, INFINITE) != WAIT_OBJECT_0)
  {
    return;
  }

  if (!GetExitCodeProcess(processInfo.hProcess, &exitcode))
  {
    return;
  }

  CloseHandle(processInfo.hProcess);
  CloseHandle(processInfo.hThread);
}

现在我的问题是,ReadFile 是否有可能立即返回而不读取任何数据,或者不从子进程 stdout 读取完整数据并且仍然返回非零值(这是成功的)?

如果是这样,那么确保读取完整数据并且只有这样我才能继续父进程的最佳方法是什么?

I would like to launch one console c++ application from another c++ application with WIN32 API CreateProcess. This child console application returns some result and i want to read the result of child process in my parent application. Here is my code.

void executeCommand(const std::string& lpCommandLine) 
{
  PROCESS_INFORMATION processInfo;
  STARTUPINFOA startupInfo;
  SECURITY_ATTRIBUTES saAttr;

  HANDLE stdoutReadHandle  = NULL;
  HANDLE stdoutWriteHandle = NULL;

  std::string outbuf;
  DWORD bytes_read;
  char tBuf[257];
  DWORD exitcode;
  BOOL bSuccess = FALSE;

  memset(&saAttr, 0, sizeof(saAttr));
  saAttr.nLength              = sizeof(SECURITY_ATTRIBUTES);
  saAttr.bInheritHandle       = TRUE;
  saAttr.lpSecurityDescriptor = NULL;



 // Create a pipe for the child process's STDOUT.
  if (!CreatePipe(&stdoutReadHandle, &stdoutWriteHandle, &saAttr, 5000))
  {
    return;
  }

  // Ensure the read handle to the pipe for STDOUT is not inherited.
  if (!SetHandleInformation(stdoutReadHandle, HANDLE_FLAG_INHERIT, 0))
  {
    return;
  }

  memset(&startupInfo, 0, sizeof(startupInfo));
  startupInfo.cb          = sizeof(startupInfo);
  startupInfo.hStdError   = stdoutWriteHandle;
  startupInfo.hStdOutput  = stdoutWriteHandle;
  startupInfo.wShowWindow = SW_HIDE;
  startupInfo.hStdInput   = GetStdHandle(STD_INPUT_HANDLE);
  startupInfo.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;

  if (!CreateProcessA(NULL, (LPSTR)lpCommandLine.c_str(), NULL, NULL, TRUE, CREATE_NEW_CONSOLE,
                      NULL,
                      0, &startupInfo,
                      &processInfo))
  {
    return;
  }

  CloseHandle(stdoutWriteHandle);

  for (;;)
  {
    bSuccess = ReadFile(stdoutReadHandle, tBuf, 256, &bytes_read, NULL);

    if (!bSuccess || bytes_read == 0)
    {
      break;
    }
    if (bytes_read > 0)
    {
      tBuf[bytes_read] = '\0';
      outbuf += tBuf;
    }
  }

  cmdOutput_ = outbuf;

  if (WaitForSingleObject(processInfo.hProcess, INFINITE) != WAIT_OBJECT_0)
  {
    return;
  }

  if (!GetExitCodeProcess(processInfo.hProcess, &exitcode))
  {
    return;
  }

  CloseHandle(processInfo.hProcess);
  CloseHandle(processInfo.hThread);
}

Now my question is, is there possibility that ReadFile returns immediately without reading any data, or without reading complete data from child process stdout and still return non-zero value (which is success)?

If so, then what is the best way to make sure that the complete data is read and only then i can continue parent process?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文