我有一个程序,通过在新的控制台窗口中创建一个新进程来执行命令。因此,在通过 WriteFile 函数在控制台中写入命令后,我得到了该窗口的句柄并尝试读取其输出。特别是我需要获取出现在新控制台中的 FarManager 窗口的输出,但 ReadConsoleOutput 会抛出一个错误 (6),告知“错误句柄”。你能提供什么想法?
这是一个获取新控制台句柄的函数。
HWND RemoteConsole::GetLastWindowsFromProcessID() {
HWND vhWnds = 0;
// find all hWnds (vhWnds) associated with a process id (dwProcessID)
HWND hCurWnd = NULL;
do
{
hCurWnd = FindWindowEx(NULL, hCurWnd, NULL, NULL);
DWORD dwProcID = 0;
GetWindowThreadProcessId(hCurWnd, &dwProcID);
if (dwProcID == pi.dwProcessId)
{
vhWnds = hCurWnd; // add the found hCurWnd
}
} while (hCurWnd != NULL);
return vhWnds;
}
void RemoteConsole::readScreen(void)
{
HANDLE hStdout, hNewScreenBuffer;
SMALL_RECT srctReadRect;
SMALL_RECT srctWriteRect;
CHAR_INFO chiBuffer[160]; // [2][80];
COORD coordBufSize;
COORD coordBufCoord;
BOOL fSuccess;
// Get a handle to the STDOUT screen buffer to copy from and
// create a new screen buffer to copy to.
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
HWND h = GetLastWindowsFromProcessID();
hNewScreenBuffer = CreateConsoleScreenBuffer(
GENERIC_READ | // read/write access
GENERIC_WRITE,
FILE_SHARE_READ |
FILE_SHARE_WRITE, // shared
NULL, // default security attributes
CONSOLE_TEXTMODE_BUFFER, // must be TEXTMODE
NULL); // reserved; must be NULL
if (h == INVALID_HANDLE_VALUE ||
hNewScreenBuffer == INVALID_HANDLE_VALUE)
{
printf("CreateConsoleScreenBuffer failed - (%d)\n", GetLastError());
return;
}
// Make the new screen buffer the active screen buffer.
if (!SetConsoleActiveScreenBuffer(hNewScreenBuffer))
{
printf("SetConsoleActiveScreenBuffer failed - (%d)\n", GetLastError());
return;
}
// Set the source rectangle.
srctReadRect.Top = 0; // top left: row 0, col 0
srctReadRect.Left = 0;
srctReadRect.Bottom = 1; // bot. right: row 1, col 79
srctReadRect.Right = 79;
// The temporary buffer size is 2 rows x 80 columns.
coordBufSize.Y = 2;
coordBufSize.X = 80;
// The top left destination cell of the temporary buffer is
// row 0, col 0.
coordBufCoord.X = 0;
coordBufCoord.Y = 0;
// Copy the block from the screen buffer to the temp. buffer.
fSuccess = ReadConsoleOutput(
h, // screen buffer to read from
chiBuffer, // buffer to copy into
coordBufSize, // col-row size of chiBuffer
coordBufCoord, // top left dest. cell in chiBuffer
&srctReadRect); // screen buffer source rectangle
if (!fSuccess)
{
printf("ReadConsoleOutput failed - (%d)\n", GetLastError());
return;
}
// Set the destination rectangle.
// Copy from the temporary buffer to the new screen buffer.
// Restore the original active screen buffer.
if (!SetConsoleActiveScreenBuffer(h))
{
printf("SetConsoleActiveScreenBuffer failed - (%d)\n", GetLastError());
return;
}
/*
std::string out;
for (size_t i = 0; i < coordBufSize.Y * coordBufSize.X; i++)
{
out += chiBuffer[i].Char.AsciiChar;
}
std::cout << out;
*/
}
您不能将 HWND 句柄与控制台 API 一起使用。 您需要与您要监视的进程关联的控制台的输入或输出缓冲区的句柄。请注意,控制台与每个命令行进程相关联(但也可以分配给 GUI 应用程序)。您有两个选择:
不要使用
CreateProcess
标志作为 CREATE_NEW_CONSOLE
参数,使用 dwCreationFlags
API 创建子进程。这将使新进程使用父进程控制台FreeConsole()
和 AttachConsole()
API 连接到另一个进程控制台。在这两种情况下,您都可以将
CreateFile
与特殊文件 "CONOUT$" 和 "CONIN$" 一起使用来获取输出和输入缓冲区。通过像这样创建的句柄,您可以开始使用 WriteFile、ReadFile 或 Console API 的读写函数。
https://learn.microsoft.com/en-us/windows/console/console-handles
https://learn.microsoft.com/en-us/windows/console/console-functions