Чтение из stdOut процесса, созданного с помощью CreateProcessWithLogonW - PullRequest
4 голосов
/ 12 августа 2011

Когда я создаю процесс с помощью CreateProcess (), я могу читать его stdOut без каких-либо проблем. Для этого я создаю трубы и передаю их процессу через STARTUPINFO. Позже я могу использовать ReadFile для чтения из stdOut.

При попытке сделать то же самое с CreateProcessWithLogonW (процесс запускается от имени другого пользователя) он не работает. Здесь ReadFile возвращает FALSE.

Итак, мои вопросы: можно ли вообще читать stdOut? Если это так, что нужно сделать иначе, чем в «нормальном» случае 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

1 Ответ

0 голосов
/ 08 ноября 2011

CreateProcessWithLogonW правильно запускает новый процесс?

Глядя на MSDN, я вижу, что CreateProcess и CreateProcessAsUser могут наследовать все дескрипторы. Я не вижу такого комментария на CreateProcessWithLogonW или CreateProcessWithTokenW. Так что я думаю, что это может не сработать.

Но вы все равно можете попробовать

  1. для LogonUser и CreateProcessAsUser или
  2. для заполнения STARTUPINFOEX :: lpAttributeList.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...