std::popen

Тема в разделе "LANGS.C", создана пользователем Dukales, 9 дек 2011.

  1. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    Скажите, есть ли что подобное _popen() удобное? (в boost не нашёл)
    Можно ли осуществить ввод и вывод одновременно, используя CreateProcess+CreatePipe+std::stringstream или, на худой конец, sscanf? Необходимо для того, чтобы управлять процессом. Парсить его вывод и выдавать соответствующие команды.
     
  2. censored

    censored New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2005
    Сообщения:
    1.615
    Адрес:
    деревня "Анонимные Прокси"
    Dukales
    Есть boost.process (www.highscore.de/boost/process/) -- там есть работа с pipe.
     
  3. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    Спасибо, посмотрю. Вряд ли у них двусторонний pipe организован.
     
  4. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Dukales

    Boost.ASIO.StreamHandle?
     
  5. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    И зачем тут нужен двухсторонний pipe?
    stdout - это один pipe, stdin - другой.
    Или два pipe использовать религия не позволяет?
     
  6. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    cppasm
    не знаю что и ответить)
     
  7. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    вообще конечно без двух пайпов не обойтись
     
  8. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    самая проблема - как парсить ввод (не самому посимвольно)
     
  9. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    Ещё один вопрос в тему:
    Хочу передавать наследуемый хэндл named pipe-а в создаваемый процесс:
    Код (Text):
    1.   SECURITY_ATTRIBUTES sa;
    2.   ZeroMemory(&sa, sizeof(sa));
    3.   sa.nLength = sizeof(sa);
    4.   sa.lpSecurityDescriptor = NULL;
    5.   sa.bInheritHandle = TRUE;
    6.   HANDLE hPipe = CreateNamedPipe(
    7.     PIPE_NAME,
    8.     PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
    9.     PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
    10.     PIPE_UNLIMITED_INSTANCES,
    11.     BUFSIZ,
    12.     BUFSIZ,
    13.     NMPWAIT_USE_DEFAULT_WAIT,
    14.     &sa
    15.   );
    16.   if (INVALID_HANDLE_VALUE == hPipe) {
    17.     throw;
    18.   }
    19.  
    20.   if (FALSE == SetHandleInformation(hPipe, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
    21.     throw;
    22.   }
    23.  
    24.   STARTUPINFO si;
    25.   ZeroMemory(&si, sizeof(si));
    26.   si.cb = sizeof(si);
    27.   si.dwFlags |= STARTF_USESTDHANDLES;
    28.   si.hStdError = hPipe;
    29.   si.hStdOutput = hPipe;
    30.   si.hStdInput = hPipe;
    31.   si.dwFlags |= STARTF_USESHOWWINDOW;
    32.   si.wShowWindow = SW_HIDE;
    33.  
    34.   PROCESS_INFORMATION pi;
    35.   pi.hProcess = INVALID_HANDLE_VALUE;
    36.   pi.hThread = INVALID_HANDLE_VALUE;
    37.  
    38.   char * fname = strdup("cmd.exe /K echo aaa");
    39.   BOOL bSuccess = CreateProcess(
    40.     NULL,
    41.     //const_cast<char *>(fname),
    42.     fname,
    43.     NULL,
    44.     NULL,
    45.     TRUE,
    46.     CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP,
    47.     NULL,
    48.     NULL,
    49.     &si,
    50.     &pi
    51.   );
    52.   free(fname);
    53.   if (FALSE == bSuccess) {
    54.     throw;
    55.   }
    56.  
    57.   OVERLAPPED oOverlap;
    58.   oOverlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
    59.   if ((FALSE != ConnectNamedPipe(hPipe, &oOverlap)) || (ERROR_IO_PENDING == GetLastError())) {
    60.     for (;;) {
    61.       ResetEvent(oOverlap.hEvent);
    62.       unsigned __int8 rx_buffer[BUFSIZ];
    63.       #define READ_TIMEOUT 1000
    64.       DWORD Read;
    65.       if (ReadFile(hPipe, rx_buffer, sizeof(rx_buffer), &Read, &oOverlap) == FALSE) {
    66.         if (GetLastError() != ERROR_IO_PENDING) {
    67.           throw;// EWinLastError();
    68.         } else {
    69.           switch (WaitForSingleObject(oOverlap.hEvent, READ_TIMEOUT)) {
    70.             case WAIT_TIMEOUT : {
    71.               throw;
    72.             }
    73.             case (WAIT_OBJECT_0) : {
    74.               if (GetOverlappedResult(hPipe, &oOverlap, &Read, FALSE) == FALSE) {
    75.                 throw;
    76.               } else {
    77.                 rx_buffer;
    78.                 goto END_FOR;
    79.               }
    80.             }
    81.             default : {
    82.               throw;
    83.             }
    84.           }
    85.         }
    86.       } else {
    87.         rx_buffer;
    88.         goto END_FOR;
    89.       }
    90.     }
    91.     END_FOR :
    92.     if (FALSE == DisconnectNamedPipe(hPipe)) {
    93.       throw;
    94.     }
    95.   } else {
    96.     throw;
    97.   }
    98.   CloseHandle(oOverlap.hEvent);
    После ReadFile GetLastError возвращает ERROR_PIPE_LISTENING: Waiting for a process to open the other end of the pipe.
    Я так понимаю, что надо было бы предварительно закрыть здесь хэндл hPipe и по новой создать. Причём в процесс передавать пайп не такой, как здесь, а с другими свойствами, а именно: со свойствами такими же, как и у пайпов, созданных CreatePipe (http://msdn.microsoft.com/en-us/library/ms682499.aspx). Читал, что анонимные пайпы — те же именованые (тоже имеют своё имя в фаловой системе), только с неизвестным именем.
    Вопрос: пайп созданный с какими параметрами передавать в дочерний процесс?
     
  10. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    Как создать пайп именованый эквивалентный анонимному?
     
  11. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    Так эти изыскания ни на чём и закончились (виснет на ReadFile - с той стороны получается CallNamedPipe должен быть, а не ReadFile/WriteFile похоже):
    Код (Text):
    1.   #define PIPE_NAME "\\\\.\\pipe\\MyPipe"
    2.  
    3.   HANDLE hPipe = CreateNamedPipe(
    4.     PIPE_NAME,
    5.     PIPE_ACCESS_DUPLEX,
    6.     PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
    7.     PIPE_UNLIMITED_INSTANCES,
    8.     BUFSIZ,
    9.     BUFSIZ,
    10.     NMPWAIT_USE_DEFAULT_WAIT,
    11.     NULL
    12.   );
    13.   if (INVALID_HANDLE_VALUE == hPipe) {
    14.     throw;
    15.   }
    16.  
    17.   SECURITY_ATTRIBUTES sa;
    18.   ZeroMemory(&sa, sizeof(sa));
    19.   sa.nLength = sizeof(sa);
    20.   sa.lpSecurityDescriptor = NULL;
    21.   sa.bInheritHandle = TRUE;
    22.   HANDLE hPipeChild = CreateFile(
    23.     PIPE_NAME,
    24.     GENERIC_READ | GENERIC_WRITE,
    25.     0,
    26.     &sa,
    27.     OPEN_EXISTING,
    28.     0,
    29.     NULL
    30.   );
    31.   if (INVALID_HANDLE_VALUE == hPipe) {
    32.     throw;
    33.   }
    34.   if (FALSE == SetHandleInformation(hPipeChild, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
    35.     throw;
    36.   }
    37.  
    38.   STARTUPINFO si;
    39.   ZeroMemory(&si, sizeof(si));
    40.   si.cb = sizeof(si);
    41.   si.dwFlags |= STARTF_USESTDHANDLES;
    42.   si.hStdError = hPipeChild;
    43.   si.hStdOutput = hPipeChild;
    44.   si.hStdInput = hPipeChild;
    45.   si.dwFlags |= STARTF_USESHOWWINDOW;
    46.   si.wShowWindow = SW_HIDE;
    47.  
    48.   PROCESS_INFORMATION pi;
    49.   pi.hProcess = INVALID_HANDLE_VALUE;
    50.   pi.hThread = INVALID_HANDLE_VALUE;
    51.  
    52.   char * fname = strdup("c:\\Program Files (x86)\\octave\\3.4.2\\bin\\gnuplot.exe");
    53.   BOOL bSuccess = CreateProcess(
    54.     NULL,
    55.     //const_cast<char *>(fname),
    56.     fname,
    57.     NULL,
    58.     NULL,
    59.     TRUE,
    60.     CREATE_NEW_PROCESS_GROUP, // CREATE_NO_WINDOW |
    61.     NULL,
    62.     NULL,
    63.     &si,
    64.     &pi
    65.   );
    66.   free(fname);
    67.   if (FALSE == bSuccess) {
    68.     throw;
    69.   }          
    70.   if (FALSE == CloseHandle(hPipeChild)) {
    71.     throw;
    72.   }
    73.                  
    74.   OVERLAPPED oOverlap;
    75.   oOverlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
    76.   #define CONNECT_TIMEOUT 2000
    77.   if (FALSE == ConnectNamedPipe(hPipe, &oOverlap)) {
    78.     if (GetLastError() == ERROR_PIPE_CONNECTED) {
    79.       asm nop
    80.     }
    81.     switch (GetLastError()) {
    82.       case ERROR_PIPE_CONNECTED : {
    83.         goto WAIT_SUCCESS;
    84.       }
    85.       case ERROR_IO_PENDING : {
    86.         switch (WaitForSingleObject(oOverlap.hEvent, CONNECT_TIMEOUT)) {
    87.           case WAIT_TIMEOUT : {
    88.             throw;
    89.           }
    90.           case (WAIT_OBJECT_0) : {
    91.             DWORD Dummy;
    92.             if (GetOverlappedResult(hPipe, &oOverlap, &Dummy, FALSE) == FALSE) {
    93.               throw;
    94.             } else {
    95.               goto WAIT_SUCCESS;
    96.             }
    97.           }
    98.           default : {
    99.             throw;
    100.           }
    101.         }
    102.       }
    103.       default : {
    104.         throw;
    105.       }
    106.     }    
    107.   } else {
    108.     throw;
    109.   }
    110.  
    111.   WAIT_SUCCESS :
    112.  
    113.   ResetEvent(oOverlap.hEvent);
    114.  
    115.   const char * command = "plot x*x;plot x*x*x;replot;\n";
    116.   DWORD Written = 0;
    117.   WriteFile(hPipe, command, strlen(command), &Written, NULL);
    118.  
    119.   unsigned __int8 rx_buffer[1 ]; // BUFSIZ
    120.   #define READ_TIMEOUT 1000
    121.   DWORD Read = 0;
    122.   if (ReadFile(hPipe, rx_buffer, sizeof(rx_buffer), &Read, NULL) == FALSE) {
    123.     if (GetLastError() != ERROR_IO_PENDING) {
    124.       throw;// EWinLastError();
    125.     } else {
    126.       switch (WaitForSingleObject(oOverlap.hEvent, READ_TIMEOUT)) {
    127.         case WAIT_TIMEOUT : {
    128.           throw;
    129.         }
    130.         case (WAIT_OBJECT_0) : {
    131.           if (GetOverlappedResult(hPipe, &oOverlap, &Read, FALSE) == FALSE) {
    132.             throw;
    133.           } else {
    134.             rx_buffer;
    135.             goto END_FOR;
    136.           }
    137.         }
    138.         default : {
    139.           throw;
    140.         }
    141.       }
    142.     }
    143.   } else {
    144.     rx_buffer;
    145.     goto END_FOR;
    146.   }
    147.   END_FOR :
    148.   if (FALSE == DisconnectNamedPipe(hPipe)) {
    149.     throw;
    150.   }
    151.   if (FALSE == CloseHandle(oOverlap.hEvent)) {
    152.     throw;
    153.   }
     
  12. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    что вам конкретно нужно? чем примеры из msdn не устраивают?
     
  13. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    охота один двусторонний пайп, а не два. "эстетическая" (по-сути, бессмысленная здесь) бритва Оккама
     
  14. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    я могу выложить свой пайп в стиле stl потока, он сделан на boost::iostreams. но он довольно большой и размазан по библиотеке. вы можете поступить так. компилировать его, смотреть, каких классов не хватает, отписываться, и я буду их выкладывать дополнительно
     
  15. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    инструмент bcb 6 - не хочу boost допиливать под него ничуть. решить задачу - не на столько принципиальная цель
     
  16. sergegers

    sergegers New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2008
    Сообщения:
    172
    этот пайп может компилироваться под boost 1.34.1 с патчем для Borland и под CodeGear 2009. но гемороя было много.
    вообщем напишите с нуля. есть книга

    Системное программирование в среде Windows
    Автор: Джонсон М. Харт
    Серия:
    Издательство: Вильямс, 2005 г.
    Страниц: 592
    ISBN: 5-8459-0879-5, 0-321-25619-0

    там описан pipe клиент и сервер на api , в msdn тоже есть