如何将 ReadConsoleOutput 函数与重定向控制台一起使用?

问题描述 投票:0回答:1

我有一个程序,通过在新的控制台窗口中创建一个新进程来执行命令。因此,在通过 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;
    */

}
c++ winapi console handle
1个回答
0
投票

您不能将 HWND 句柄与控制台 API 一起使用。 您需要与您要监视的进程关联的控制台的输入或输出缓冲区的句柄。请注意,控制台与每个命令行进程相关联(但也可以分配给 GUI 应用程序)。您有两个选择:

  1. 通过传递 bInheritHandles = TRUE 和
    不要使用
    CreateProcess标志作为
    CREATE_NEW_CONSOLE
    参数,使用
    dwCreationFlags
    API 创建子进程。这将使新进程使用父进程控制台
  2. 通过调用
    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

© www.soinside.com 2019 - 2024. All rights reserved.