从使用CreateProcessWithLogonW创建的进程的stdOut读取

时间:2011-08-12 08:09:35

标签: winapi

当我使用CreateProcess()创建一个进程时,我可以从它的stdOut中读取而没有任何问题。为此,我创建了管道并通过STARTUPINFO将它们传递给流程。后来我可以使用ReadFile从stdOut中读取。

当尝试使用CreateProcessWithLogonW执行相同的操作(该进程以不同的用户身份启动)时,它不起作用。这里ReadFile返回FALSE。

所以我的问题是:甚至可以阅读stdOut吗?如果是这样,那么必须对“普通”CreateProcess案例做些什么?

谢谢!

BTW: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

1 个答案:

答案 0 :(得分:0)

CreateProcessWithLogonW正确启动新进程吗?

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

但你仍然可以尝试

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