Скажите, есть ли что подобное _popen() удобное? (в boost не нашёл) Можно ли осуществить ввод и вывод одновременно, используя CreateProcess+CreatePipe+std::stringstream или, на худой конец, sscanf? Необходимо для того, чтобы управлять процессом. Парсить его вывод и выдавать соответствующие команды.
И зачем тут нужен двухсторонний pipe? stdout - это один pipe, stdin - другой. Или два pipe использовать религия не позволяет?
Ещё один вопрос в тему: Хочу передавать наследуемый хэндл named pipe-а в создаваемый процесс: Код (Text): SECURITY_ATTRIBUTES sa; ZeroMemory(&sa, sizeof(sa)); sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; HANDLE hPipe = CreateNamedPipe( PIPE_NAME, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZ, BUFSIZ, NMPWAIT_USE_DEFAULT_WAIT, &sa ); if (INVALID_HANDLE_VALUE == hPipe) { throw; } if (FALSE == SetHandleInformation(hPipe, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { throw; } STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdError = hPipe; si.hStdOutput = hPipe; si.hStdInput = hPipe; si.dwFlags |= STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; PROCESS_INFORMATION pi; pi.hProcess = INVALID_HANDLE_VALUE; pi.hThread = INVALID_HANDLE_VALUE; char * fname = strdup("cmd.exe /K echo aaa"); BOOL bSuccess = CreateProcess( NULL, //const_cast<char *>(fname), fname, NULL, NULL, TRUE, CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi ); free(fname); if (FALSE == bSuccess) { throw; } OVERLAPPED oOverlap; oOverlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); if ((FALSE != ConnectNamedPipe(hPipe, &oOverlap)) || (ERROR_IO_PENDING == GetLastError())) { for (;;) { ResetEvent(oOverlap.hEvent); unsigned __int8 rx_buffer[BUFSIZ]; #define READ_TIMEOUT 1000 DWORD Read; if (ReadFile(hPipe, rx_buffer, sizeof(rx_buffer), &Read, &oOverlap) == FALSE) { if (GetLastError() != ERROR_IO_PENDING) { throw;// EWinLastError(); } else { switch (WaitForSingleObject(oOverlap.hEvent, READ_TIMEOUT)) { case WAIT_TIMEOUT : { throw; } case (WAIT_OBJECT_0) : { if (GetOverlappedResult(hPipe, &oOverlap, &Read, FALSE) == FALSE) { throw; } else { rx_buffer; goto END_FOR; } } default : { throw; } } } } else { rx_buffer; goto END_FOR; } } END_FOR : if (FALSE == DisconnectNamedPipe(hPipe)) { throw; } } else { throw; } 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). Читал, что анонимные пайпы — те же именованые (тоже имеют своё имя в фаловой системе), только с неизвестным именем. Вопрос: пайп созданный с какими параметрами передавать в дочерний процесс?
Так эти изыскания ни на чём и закончились (виснет на ReadFile - с той стороны получается CallNamedPipe должен быть, а не ReadFile/WriteFile похоже): Код (Text): #define PIPE_NAME "\\\\.\\pipe\\MyPipe" HANDLE hPipe = CreateNamedPipe( PIPE_NAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZ, BUFSIZ, NMPWAIT_USE_DEFAULT_WAIT, NULL ); if (INVALID_HANDLE_VALUE == hPipe) { throw; } SECURITY_ATTRIBUTES sa; ZeroMemory(&sa, sizeof(sa)); sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; HANDLE hPipeChild = CreateFile( PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, NULL ); if (INVALID_HANDLE_VALUE == hPipe) { throw; } if (FALSE == SetHandleInformation(hPipeChild, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { throw; } STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdError = hPipeChild; si.hStdOutput = hPipeChild; si.hStdInput = hPipeChild; si.dwFlags |= STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; PROCESS_INFORMATION pi; pi.hProcess = INVALID_HANDLE_VALUE; pi.hThread = INVALID_HANDLE_VALUE; char * fname = strdup("c:\\Program Files (x86)\\octave\\3.4.2\\bin\\gnuplot.exe"); BOOL bSuccess = CreateProcess( NULL, //const_cast<char *>(fname), fname, NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP, // CREATE_NO_WINDOW | NULL, NULL, &si, &pi ); free(fname); if (FALSE == bSuccess) { throw; } if (FALSE == CloseHandle(hPipeChild)) { throw; } OVERLAPPED oOverlap; oOverlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); #define CONNECT_TIMEOUT 2000 if (FALSE == ConnectNamedPipe(hPipe, &oOverlap)) { if (GetLastError() == ERROR_PIPE_CONNECTED) { asm nop } switch (GetLastError()) { case ERROR_PIPE_CONNECTED : { goto WAIT_SUCCESS; } case ERROR_IO_PENDING : { switch (WaitForSingleObject(oOverlap.hEvent, CONNECT_TIMEOUT)) { case WAIT_TIMEOUT : { throw; } case (WAIT_OBJECT_0) : { DWORD Dummy; if (GetOverlappedResult(hPipe, &oOverlap, &Dummy, FALSE) == FALSE) { throw; } else { goto WAIT_SUCCESS; } } default : { throw; } } } default : { throw; } } } else { throw; } WAIT_SUCCESS : ResetEvent(oOverlap.hEvent); const char * command = "plot x*x;plot x*x*x;replot;\n"; DWORD Written = 0; WriteFile(hPipe, command, strlen(command), &Written, NULL); unsigned __int8 rx_buffer[1 ]; // BUFSIZ #define READ_TIMEOUT 1000 DWORD Read = 0; if (ReadFile(hPipe, rx_buffer, sizeof(rx_buffer), &Read, NULL) == FALSE) { if (GetLastError() != ERROR_IO_PENDING) { throw;// EWinLastError(); } else { switch (WaitForSingleObject(oOverlap.hEvent, READ_TIMEOUT)) { case WAIT_TIMEOUT : { throw; } case (WAIT_OBJECT_0) : { if (GetOverlappedResult(hPipe, &oOverlap, &Read, FALSE) == FALSE) { throw; } else { rx_buffer; goto END_FOR; } } default : { throw; } } } } else { rx_buffer; goto END_FOR; } END_FOR : if (FALSE == DisconnectNamedPipe(hPipe)) { throw; } if (FALSE == CloseHandle(oOverlap.hEvent)) { throw; }
я могу выложить свой пайп в стиле stl потока, он сделан на boost::iostreams. но он довольно большой и размазан по библиотеке. вы можете поступить так. компилировать его, смотреть, каких классов не хватает, отписываться, и я буду их выкладывать дополнительно
инструмент bcb 6 - не хочу boost допиливать под него ничуть. решить задачу - не на столько принципиальная цель
этот пайп может компилироваться под boost 1.34.1 с патчем для Borland и под CodeGear 2009. но гемороя было много. вообщем напишите с нуля. есть книга Системное программирование в среде Windows Автор: Джонсон М. Харт Серия: Издательство: Вильямс, 2005 г. Страниц: 592 ISBN: 5-8459-0879-5, 0-321-25619-0 там описан pipe клиент и сервер на api , в msdn тоже есть