Почему нельзя прервать вызов ReadConsole?
Представьте, что где-то в коде есть такой кусок:
BOOL Res =
ReadConsole(
GetStdHandle(STD_INPUT_HANDLE),
Buffer,
sizeof(Buffer),
&ReadChars,
NULL);
Теперь, скажем, нам в какой-то момент нужно корректно прервать вызов ReadConsole() (из другого потока). Как это сделать?
Как выясняется, ни CancelIoEx(), ни CancelSynchronousIo() не работают в этом случае. CancelIoEx() возвращает ошибку ERROR_INVALID_HANDLE, а CancelSynchronousIo() – ERROR_OBJECT_NOT_FOUND. Также интересно, то GetStdHandle() возвращает значение “3”, что не очень-то похоже на описатель (handle) ядерного объекта.
Проблема заключается в том, что консольная подсистема обслуживается системным процессом Csrss (в Windows 7 – Conhost). Консольные функции вроде ReadConsole() на самом деле выполняют RPC вызовы в Csrss, вместо обращения в ядро. Соответственно, прервать текущую операцию можно было бы вызвав CancelIoEx() с описателем LPC порта, поверх которого «ходит» RPC. Правда добраться до этого описателя не очень реально. Да и RPC соединение после такого финта ушами может быть потеряно.
Остаются всякие окольные методы. Во-первых, можно насильно завершить поток, читающий консоль. Во-вторых, можно имитировать консольный ввод с помощью WriteConsoleInput(), разблокировав тем самым ReadConsole(). В некоторых случаях можно отказаться от построчного ввода и реализовать ReadConsole() в виде надстройки над ReadConsoleInput(). Хотя этот путь только для настоящих джедаев. В общем, не просто это все…
Вы уволены.
Иногда у меня создаётся впечатление, что работа с консолью и параметрами командной строки в Windows настолько извращенной сделана осознанно, а вовсе не является результатом последовательных компромиссов и необходимости обратной совместимости, как это видно в других местах API.
Например, я так и не нашёл примера программы, которая могла бы работать с командной строки, читала и писала в консоль, из которой была запущена – но при запуске без параметров запускала бы отдельное собственное окно.
Э нет, это Вы уволены.
Необходимость с компромиссах возникает, если изначальный дизайн не соответствует сегодняшним реалиям. Иногда это означает, что критерии изменились и изначально неплохой дизайн стал плохим. В других случаях это говорит о том, что дизайн с самого начала никуда не годился.
Я не возмусь судить что произошло в данном случае. Консоль в Windows традиционна заброшена маркетологами и, в результате, не получала должного внимания (читай – денег на разработку) == развития.
Элементарно, Ватсон. Программа собирается как GUI приложение. Из WinMain вызывается либо AttachConsole, либо AllocConsole в зависимости от параметров. Цикл сообщений не создается.
Можно зайти с другой стороны. Сравните “start” и “start /B”. Если указан /B, то флаг CREATE_NEW_CONSOLE в CreateProcess не передается.
http://msdn.microsoft.com/en-us/library/cc307398.aspx#ctl00_MTCS_main_ctl04_code
?