因此,我试图修改Microsoft(here)提供的代码以使用WriteConsoleInput而不是WriteFile,但是它说该句柄无效(我敢打赌这确实很愚蠢),例如最初创建该句柄的方式等。
所以我的问题是,WriteConsoleInput和WriteFile的句柄之间有什么区别?
WriteConsoleInput
WriteFile
我猜想这与CreateFile / CreatePipe / DuplicateHandle流程创建的继承句柄相比,CreateFile创建的HANDLE的权限标志影响很大。
我认为,如果您可以看到此问题,它将变得更加容易,因此这是我的完整解决方案(使用Visual Studio 2012),包括子应用程序和父应用程序。
ConsoleRedir on GitHub
需要说明的是,我需要子应用程序使用ReadConsoleInput,这是我感到沮丧的原因。
原始方法:
///////////////////////////////////////////////////////////////////////
// GetAndSendInputThreadOrig
// Thread procedure that monitors the console for input and sends input
// to the child process through the input pipe.
// This thread ends when the child application exits.
// Original from http://support.microsoft.com/kb/190351
///////////////////////////////////////////////////////////////////////
DWORD WINAPI GetAndSendInputThreadOrig(LPVOID lpvThreadParam)
{
CHAR read_buff[256];
DWORD nBytesRead,nBytesWrote;
HANDLE hPipeWrite = (HANDLE)lpvThreadParam;
// Get input from our console and send it to child through the pipe.
while (bRunThread)
{
if(!ReadConsole(hStdIn,read_buff,1,&nBytesRead,NULL))
DisplayError("ReadConsole");
read_buff[nBytesRead] = '\0'; // Follow input with a NULL.
if (!WriteFile(hPipeWrite,read_buff,nBytesRead,&nBytesWrote,NULL))
{
if (GetLastError() == ERROR_NO_DATA)
break; // Pipe was closed (normal exit path).
else
DisplayError("WriteFile");
}
}
return 1;
}
我的修改版本(必须建立按键):
///////////////////////////////////////////////////////////////////////
// GetAndSendInputThread
// Thread procedure that monitors the console for input and sends input
// to the child process through the input pipe.
// This thread ends when the child application exits.
///////////////////////////////////////////////////////////////////////
DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam)
{
CHAR read_buff[256];
DWORD nBytesWrote;
HANDLE hPipeWrite = (HANDLE)lpvThreadParam;
// Get input from our console and send it to child through the pipe.
while (bRunThread)
{
INPUT_RECORD inputRecords[4];
// Build a keyboard event, press '?' and then press RETURN
inputRecords[0].EventType = KEY_EVENT;
inputRecords[0].Event.KeyEvent.bKeyDown = TRUE;
inputRecords[0].Event.KeyEvent.uChar.UnicodeChar = '?';
inputRecords[1].EventType = KEY_EVENT;
inputRecords[1].Event.KeyEvent.bKeyDown = FALSE;
inputRecords[1].Event.KeyEvent.uChar.UnicodeChar = '?';
inputRecords[2].EventType = KEY_EVENT;
inputRecords[2].Event.KeyEvent.bKeyDown = TRUE;
inputRecords[2].Event.KeyEvent.dwControlKeyState = 0;
inputRecords[2].Event.KeyEvent.uChar.UnicodeChar = '\r';
inputRecords[2].Event.KeyEvent.wRepeatCount = 1;
inputRecords[2].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
inputRecords[2].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC);
inputRecords[3].EventType = KEY_EVENT;
inputRecords[3].Event.KeyEvent.bKeyDown = FALSE;
inputRecords[3].Event.KeyEvent.dwControlKeyState = 0;
inputRecords[3].Event.KeyEvent.uChar.UnicodeChar = '\r';
inputRecords[3].Event.KeyEvent.wRepeatCount = 1;
inputRecords[3].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
inputRecords[3].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC);
if (!WriteConsoleInput(hPipeWrite,inputRecords,sizeof(inputRecords) / sizeof(*inputRecords),&nBytesWrote))
{
if (GetLastError() == ERROR_NO_DATA)
break; // Pipe was closed (normal exit path).
else
DisplayError("WriteConsoleInput");
}
}
return 1;
}
最佳答案
WriteConsoleInput
要求句柄是“控制台输入缓冲区的句柄”。 (问题链接页面中handle
输入参数的描述中的第一句话)。
您需要使用 GetStdHandle
中的句柄来获取合适的句柄。WriteConsoleInput
仅在控制台的直接句柄上起作用,而不在重定向的管道或类似控件上起作用。
关于c++ - 为什么一个HANDLE不适用于WriteConsoleInput,但适用于WriteFile?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17650336/