Что происходит с stdin при вызове _popen?
Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain
Добрый день.
Имеется консольное приложение (плагин для FAR).
Требуется в процессе чтения потока, созданного _popen, перехватывать нажатие ESC. Если вместо pipe читать, например, файл, то ReadConsoleInput отлично работает. Стоит только вызвать _popen, как события клавиатуры уходят мимо...
Имеется консольное приложение (плагин для FAR).
Требуется в процессе чтения потока, созданного _popen, перехватывать нажатие ESC. Если вместо pipe читать, например, файл, то ReadConsoleInput отлично работает. Стоит только вызвать _popen, как события клавиатуры уходят мимо...
Вообще-то, функция станд.библиотеки (CRT) _popen создает канал и перенаправляет в него вывод команды, указанной в качестве параметра. Читать/писать из/в него надо с помощью CTR-функций типа fgetc, fgets/fputc, fputs. При чем здесь ReadConsoleInput?
Возможно, я недостаточно понятно описал проблему. Запускается плагин из FAR, который инициирует процесс на удаленной машине и читает ее stdout. Но процесс может затянуться, поэтому хотелось бы иметь возможность прервать его. ReadConsoleInput нужен, чтобы определить, был ли нажат ESC. Если вместо открытия потока читать, например, большой файл, возможность диагностировать ESC есть. При использовании _popen() - нет.
Все равно непонятно
Еще раз повторяю: _popen() асинхронно запускает копию командного процессора, выполняет в ней консольную программу локально и позволяет перенаправить ее ввод-вывод в возвращаемый поток (буферизованный файл). Поскольку возвращается FILE*, для доступа к нему надо использовать стандартные функции чтения-записи типа fgets()/fputs(). WinAPI-функция ReadConsoleInput() и иже с ней предоставляют альтернативный вар-т для того же самого, но обладают большей функциональностью. Но она требует, чтобы и поток был создан с помощью API-шной функции типа CreatePipe(), ведь первый параметр ReadConsoleInput() - хэндл буфера ввода.
Короче, приведите фрагмент кода - посмотрим.

Короче, приведите фрагмент кода - посмотрим.
Код: Выделить всё
// -------------------------------------------------------------------------
static bool CheckForEsc( HANDLE hStdin )
{
DWORD cNumRead;
INPUT_RECORD irInBuf[128];
int i = 0;
GetNumberOfConsoleInputEvents( hStdin, &cNumRead );
if( !cNumRead ) return false;
if ( !ReadConsoleInput(
hStdin, // input buffer handle
irInBuf, // buffer to read into
1, // size of read buffer
&cNumRead)) // number of records read
{
return false;
}
if( cNumRead == 0 ) return false;
for( i = 0; i < cNumRead; i++ ) {
if( irInBuf[i].EventType == KEY_EVENT &&
irInBuf[i].Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE ) return true;
}
return false;
}
// -------------------------------------------------------------------------
static void Do( void )
{
HANDLE hStdin = GetStdHandle( STD_INPUT_HANDLE );
char buf[256];
FILE *pf = _popen( "rsh server \"ls -l\"", "rt" );
while( !feof( pf )) {
// проверим, не нажал ли пользователь ESC
if( CheckForEsc( hStdin )) return;
if( fgets( buf, 255, pf ) != NULL ) {
// что - то делаем
}
}
}
// -------------------------------------------------------------------------
Понятно. Команда rsh перенаправляет STDIN на удаленный хост, поэтому после ее запуска через _popen() бессмысленно читать локальный STDIN (через hStdin). А с fopen(), естественно, работает: она ведь не подменяет стандартный вход, и Вы просто читаете что есть с локальной консоли. Попробуйте такой финт ушами: задайте вместо удаленного localhost - если я прав, в этом случае должно работать.
Попробовал с localhost - эффект тот же. Но даже если предположить, что такой вариант работоспособен - он мне, к сожалению, не подходит.
Но вот ведь что интересно - все, что вводится с клавиатуры в процессе чтения потока, отображается на консоли, а перехватить не получается.
Но вот ведь что интересно - все, что вводится с клавиатуры в процессе чтения потока, отображается на консоли, а перехватить не получается.
Тады не знаю... А rsh -то работает реально? Читаете что-нибудь с remotehost?
да, с удаленного хоста читаю все без проблем. да ладно, и так получилось нормально. можно и без ESC обойтись 

Если все-таки захотите использовать ESC, можно еще поставить хук на консольное окно и ловить WM_KEYDOWN. Но это уже вариант на любителя 
PS Если что, смогу ответить после 16.00

PS Если что, смогу ответить после 16.00