Получить содержимое буфера консоли в C - PullRequest
2 голосов
/ 30 ноября 2008

Просто интересно, есть ли какой-нибудь способ (в C) получить содержимое буфера консоли, предпочтительно в виде некоторого массива char. Он будет записан в файл, так что, если я упускаю что-то глупое, которое сделает именно это, то укажите на это. Это может быть для Windows. Я использую MinGW (gcc 3.4.5).

Заранее спасибо.

Ответы [ 5 ]

4 голосов
/ 01 декабря 2008

Я думаю, вам нужно взглянуть на функции консоли win32, например: GetStdHandle () , ReadConsoleOutput () , WriteConsoleOutput и т. Д.

4 голосов
/ 01 декабря 2008

В Win32, ReadConsoleOutput :

Считывает данные символьных и цветовых атрибутов из прямоугольного блока символьных ячеек в экранном буфере консоли, а функция записывает данные в прямоугольный блок в указанном месте в целевом буфере.

1 голос
/ 01 декабря 2008

Скачать mingw-readline

И посмотрите GNU Readline

rl_line_buffer
0 голосов
/ 05 ноября 2016

Вот способ чтения буфера консоли. GetNumCharsInConsoleBuffer - чтобы получить общее количество символов, записанных в буфер экрана консоли, я использую GetConsoleScreenBufferInfo внутри. После этого я создаю динамически размещенный массив размером, равным предыдущему значению, возвращаемому GetNumCharsInConsoleBuffer + 1 (для нулевого конца). И наконец, ReadConsoleBuffer заполнит только что созданный буфер содержимым экранного буфера консоли. После, если вы хотите записать содержимое вашего буфера в файл, вам, вероятно, потребуется выполнить некоторое форматирование. С ReadConsoleOutputCharacter вы получаете область (прямоугольник) экранного буфера консоли. Строки, которые вы записали в экранный буфер консоли, будут заполнены пробелами, чтобы соответствовать области буфера. то же самое будет с win32 ReadConsoleOutput/WriteConsoleOutput, вы получите область (прямоугольник) вашего экрана.

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

DWORD GetNumCharsInConsoleBuffer()
{
    CONSOLE_SCREEN_BUFFER_INFO buffer_info = {0};
    if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &buffer_info) != FALSE)
        return (DWORD) ( (buffer_info.dwSize.X * ( buffer_info.dwCursorPosition.Y + 1)) - (buffer_info.dwSize.X - ( buffer_info.dwCursorPosition.X)) );
    else
        return 0;
}

DWORD ReadConsoleBuffer(char* buffer, DWORD bufsize)
{
    DWORD num_character_read = 0;
    COORD first_char_to_read = {0};
    if( ReadConsoleOutputCharacterA(GetStdHandle(STD_OUTPUT_HANDLE), buffer, bufsize, first_char_to_read, &num_character_read) != FALSE)
        buffer[bufsize-1] = '\0';
    else
        buffer[0] = '\0';

    return num_character_read;
}

int main(int argc, char** argv)
{
    fprintf(stdout, "Writting\nin\nthe\nbuffer\n");
    DWORD bufsize = GetNumCharsInConsoleBuffer();

    if(bufsize > 0)
    {
        bufsize++; // Add 1 for zero-ending char

        char* buffer = malloc(bufsize);
        memset(buffer, 0, bufsize);

        ReadConsoleBuffer(buffer, bufsize);  

        puts("\nBuffer contents:");
        puts(buffer);

        free(buffer);
    }

    system("pause"); 
    return 0;
}

Выход:

Writting
in
the
buffer
Buffer contents:
Writting
in
the
buffer

Appuyez sur une touche pour continuer...

EDIT:

Я только что написал функцию, которую можно использовать для записи содержимого экранного буфера в файл. Эта функция удаляет дополненные пробелы из буфера консоли экрана. ReadConsoleBuffer принимает нулевой указатель на символ в качестве первого аргумента (buffer), который будет выделен во время его выполнения. Так что не забудьте удалить его самостоятельно. ReadConsoleBuffer запишет размер буфера во втором аргументе (bufsize).

#include <stdio.h>
#include <stdlib.h>
#include <crtdbg.h>
#include <Windows.h>

const char* ReadConsoleBuffer(char** buffer, size_t* bufsize)
{
    CONSOLE_SCREEN_BUFFER_INFO buffer_info = {0};
    if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &buffer_info) != FALSE )
    {
        size_t data_size = (size_t) ( (buffer_info.dwSize.X * ( buffer_info.dwCursorPosition.Y + 1)) - 
                                      (buffer_info.dwSize.X - ( buffer_info.dwCursorPosition.X + 1)) );

        if(data_size > 1)
        {
            char* data = malloc(data_size); //= new char[data_size];
            _ASSERTE(data != 0);

            DWORD num_char_read;
            COORD first_char_read = {0};
            if( ReadConsoleOutputCharacterA(GetStdHandle(STD_OUTPUT_HANDLE), data, data_size, first_char_read, &num_char_read) != FALSE )
            {
                data[data_size-1] = '\0';

                const char* const pbeg = &data[0];
                const char* const pend = &data[data_size-1];
                char* pcur, *pmem;

                const int line_size = buffer_info.dwSize.X;
                int line_count = buffer_info.dwCursorPosition.Y;

                if(buffer_info.dwCursorPosition.X > 0) // No new line char at the end of the last line, so no padded spaces. 
                {                    
                    if((line_count + 1) > 1)
                    {
                        pmem = &data[data_size - buffer_info.dwCursorPosition.X - 1];
                        pcur = (pmem - 1);
                    }
                    else // 1 line and no new line char(no padded spaces). Will no enters the loop.
                        pcur = &data[0];
                }
                else 
                {
                    pcur = &data[data_size-2];
                    pmem = 0;
                }

                if(pcur != pbeg)
                {
                    while(1)
                    {
                        line_count--;

                        while(*pcur == ' ') { pcur--; }
                        *(pcur + 1) = '\n'; // Padded spaces replaced by new line char.

                        if(!pmem) // first round. Add zero-ending char.
                            *(pcur + 2) = '\0'; 
                        else
                            memmove(pcur + 2, pmem, (pend - pmem) + 1);

                        if(line_count == 0)
                            break;

                        pmem = &data[line_count * line_size];
                        pcur = (pmem - 1);
                    }
                }

                *bufsize = strlen(data) + 1;

                *buffer = malloc(*bufsize); //= new char[*bufsize];
                _ASSERTE(*buffer != 0);

                memcpy(*buffer, data, *bufsize);
                free(data); //delete[] data;

                pcur= *buffer;
                return pcur;
            }

            if(data)
                free(data); // delete[] data;
        }
    }

    *buffer = 0;
    return 0;
}


int main(int argc, char** argv)
{
    printf("Writting\nin\nthe\nbuffer");

    char* buffer;
    size_t size;  
    ReadConsoleBuffer(&buffer, &size);

    if(buffer)
    {
        freopen("out.txt", "w", stdout); 
        fprintf(stdout, buffer);
        free(buffer);
        fclose(stdout);
    }  

    return 0;
}

Вывод в out.txt:

Writting
in
the
buffer
0 голосов
/ 01 декабря 2008

Если это экран в командном окне, то потенциально нет, или нет простого способа. Вы можете взломать события Windows, чтобы выделить все, скопировать и прочитать буфер обмена.

...