【问题标题】:Reading from stdOut of a process created with CreateProcessWithLogonW从使用 CreateProcessWithLogonW 创建的进程的 stdOut 中读取
【发布时间】:2011-08-12 08:09:34
【问题描述】:

当我使用 CreateProcess() 创建一个进程时,我可以毫无问题地从它的 stdOut 中读取。为此,我创建了管道并通过 STARTUPINFO 将它们传递给进程。稍后我可以使用 ReadFile 从 stdOut 中读取。

当尝试用 CreateProcessWithLogonW 做同样的事情时(进程作为不同的用户启动)它不起作用。这里 ReadFile 返回 FALSE。

所以我的问题是:甚至可以读取标准输出吗?如果是这样,与“正常”的 CreateProcess 案例有什么不同?

谢谢!

顺便说一句:GetLastError 给了我

*ERROR_BROKEN_PIPE 109 (0x6D) 管道已结束。*

在调用 ReadFile 之后。

编辑:这是代码。它包括两条路径,一条使用 CreateProcess(有效),一条使用 CreateProcessWithLogonW(无效)。

  // Declare handles
  HANDLE g_hChildStd_IN_Rd = NULL;
  HANDLE g_hChildStd_OUT_Rd = NULL;
  HANDLE g_hChildStd_OUT_Wr = NULL;

  // Create security attributes
  SECURITY_ATTRIBUTES saAttr;
  saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
  saAttr.bInheritHandle = TRUE;
  saAttr.lpSecurityDescriptor = NULL;

  bool success = true;

  // Create a pipe for the child process's STDOUT
  if(!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) 
    success = false;

  // Ensure the read handle to the pipe for STDOUT is not inherited
  if(success)
    if(!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
      success = false;

  if(success)
  {
    BOOL bSuccess = FALSE; 

    // Set up members of the PROCESS_INFORMATION structure
    PROCESS_INFORMATION piProcInfo; 
    ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );

    if(!isRemote) // WORKS
    {
      // Declare process info
      STARTUPINFO siStartInfo;

      // Set up members of the STARTUPINFO structure. 
      // This structure specifies the STDIN and STDOUT handles for redirection.
      ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
      siStartInfo.cb = sizeof(STARTUPINFO); 
      siStartInfo.hStdError = g_hChildStd_OUT_Wr;
      siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
      siStartInfo.hStdInput = g_hChildStd_IN_Rd;
      siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

      // Create the child process. 
      bSuccess = CreateProcess(NULL, 
        fullCmdLPSTR,  // command line 
        NULL,          // process security attributes 
        NULL,          // primary thread security attributes 
        TRUE,          // handles are inherited 
        0,             // creation flags 
        NULL,          // use parent's environment 
        NULL,          // use parent's current directory 
        &siStartInfo,  // STARTUPINFO pointer 
        &piProcInfo);  // receives PROCESS_INFORMATION
    }
    else // RESULTS IN A BROKEN/ENDED PIPE
    {
      STARTUPINFOW siStartInfo;

      // Set up members of the STARTUPINFOW structure. 
      // This structure specifies the STDIN and STDOUT handles for redirection.
      ZeroMemory( &siStartInfo, sizeof(STARTUPINFOW) );
      siStartInfo.cb = sizeof(STARTUPINFOW); 
      siStartInfo.hStdError = g_hChildStd_OUT_Wr;
      siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
      siStartInfo.hStdInput = g_hChildStd_IN_Rd;
      siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

      bSuccess = CreateProcessWithLogonW(L"otherUser",
                              L".",
                              L"otherPW",
                              LOGON_WITH_PROFILE,
                              myExeName,
                              (LPWSTR)cmdLine.c_str(),
                              CREATE_UNICODE_ENVIRONMENT,
                              NULL,
                              NULL,
                              &siStartInfo,
                              &piProcInfo);
    }//end if

    // If an error occurs...
    if(!bSuccess) 
    {
      success = false;
    }
    else 
    {
      // Close handles to the child process and its primary thread
      CloseHandle(piProcInfo.hProcess);
      CloseHandle(piProcInfo.hThread);
    }//end if

    if(success)
    {
      // Read output from the child process's pipe for STDOUT
      // Stop when there is no more data. 
      DWORD dwRead; 
      CHAR chBuf[4096]; 
      bSuccess = FALSE;

      // Close the write end of the pipe before reading from the 
      // read end of the pipe, to control child process execution.
      // The pipe is assumed to have enough buffer space to hold the
      // data the child process has already written to it.
      if(!CloseHandle(g_hChildStd_OUT_Wr)) 
        success = false;

      if(success)
      {
        while(true)
        { 
          bSuccess = ReadFile( g_hChildStd_OUT_Rd, chBuf, 4096, &dwRead, NULL);

          // When using CreateProcess everything is fine here
          // When using CreateProcessWithLogonW bSuccess is FALSE and the pipe seems to be closed

          if( ! bSuccess || dwRead == 0 ) break; 
          chBuf[dwRead] = '\0';

          // Write read line
          write(chBuf);
        }//end while
      }//end if
    }//end if
  }//end if

【问题讨论】:

  • 听起来你没有检查 CreateProcess 的返回值。不要让我们猜测这个,发布代码的sn-p。
  • 进程启动正常(返回值没问题)。我很快就会发布一些代码......

标签: winapi


【解决方案1】:

CreateProcessWithLogonW 是否正确启动新进程?

查看 MSDN 我看到 CreateProcess 和 CreateProcessAsUser 可以继承所有句柄。我没有在 CreateProcessWithLogonW 或 CreateProcessWithTokenW 上看到这样的评论。所以我的猜测是它可能不适合你。

但你还是可以试试

  1. 到 LogonUser 和 CreateProcessAsUser 或
  2. 填写STARTUPINFOEX::lpAttributeList。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    • 2016-02-11
    • 2010-11-12
    • 1970-01-01
    • 2018-03-17
    • 1970-01-01
    相关资源
    最近更新 更多