Using overlapped IO for console input?

2019-01-25 16:34发布

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;
}

1条回答
何必那么认真
2楼-- · 2019-01-25 17:14

When you open CONIN$ or CONOUT$ the parameter dwFlagsAndAttributes 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 by CreateFile directly to the WaitForSingleObject 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.

查看更多
登录 后发表回答