I'm attempting to use overlapped IO to read input from the console by opening CONIN$ with the FILE_FLAG_OVERLAPPED flag. However, ReadFile blocks when I use it, even with an OVERLAPPED parameter.
I've read some posts reporting that this is a Windows 7 bug. I am using 7 so that could be possible.
Here's the code I'm using:
// Create a console window
AllocConsole();
AttachConsole(GetProcessId(GetModuleHandle(NULL)));
HANDLE overlappedConsoleIn = CreateFile(L"CONIN$",
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
NULL);
// Set up the console to work with stdio
FILE *consoleOut = _fdopen(_open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT), "w");
FILE *consoleIn = _fdopen(_open_osfhandle((long)overlappedConsoleIn, _O_TEXT), "r");
*stdout = *consoleOut;
*stdin = *consoleIn;
setvbuf(consoleOut, NULL, _IONBF, 0);
setvbuf(consoleIn, NULL, _IONBF, 0);
std::ios::sync_with_stdio();
// Create a completion event
HANDLE inputEvent = CreateEvent(NULL, true, false, NULL);
BYTE inputBuffer[128];
OVERLAPPED overlappedData;
overlappedData.Offset = 0;
overlappedData.OffsetHigh = 0;
overlappedData.hEvent = inputEvent;
DWORD numBytesRead = 0;
// Asynchronously read from console
ReadFile(overlappedConsoleIn, inputBuffer, 128, &numBytesRead, &overlappedData);
while(true)
{
if(WaitForSingleObject(inputEvent, 0) == WAIT_OBJECT_0)
{
std::cout << "input has been received" << std::endl;
}
std::cout << "doing something" << std::endl;
}
When you open
CONIN$
orCONOUT$
the parameterdwFlagsAndAttributes
is ignored (in the documentation of the CreateFile function is a complete description about how to open the console). If you like to read the console asynchronously, you can pass the handle returned byCreateFile
directly to theWaitForSingleObject
function and if any Console event is pending this handle would be signaled, with the function ReadConsoleInput do you read the pending events. Here is the complete documentation of how to use the console in windows.