开发者

Reading from stdOut of a process created with CreateProcessWithLogonW

When I create a process with CreateProcess() I can read from its stdOut without any problems. To do so I create the pipes and pass them to the process via the STARTUPINFO. Later I can use ReadFile to read from the stdOut.

When trying to do the same thing with CreateProcessWithLogonW (the process is launched as a different user) it does not work. Here ReadFile returns FALSE.

So my questions are: Is it even possible to read the stdOut? If so, what has to be done differently to the "normal" CreateProcess-case?

Thanks!

BTW: GetLastError gives me

*ERROR_BROKEN_PIPE 109 (0x6D) The pipe has been ended.*

after calling ReadFile.

Edit: Here's the code. It includes two paths, one with CreateProcess (works) and one with CreateProcessWithLogonW (does not work).

  // 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,
                              &开发者_StackOverflow中文版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


CreateProcessWithLogonW starts the new process correctly?

Looking at MSDN I see that CreateProcess and CreateProcessAsUser can inherit all handles. I do not see such a comment on CreateProcessWithLogonW or CreateProcessWithTokenW. So my guess is that it might not work your way.

But you still might try

  1. to LogonUser and CreateProcessAsUser or
  2. to fill in STARTUPINFOEX::lpAttributeList.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜