Question

Just wondering if there is any way (in C) to get the contents of the console buffer, preferably as some kind of char array. It is going to be written to a file, so if I am missing out on something stupid that will do exactly that, then point it out. It can be Windows-specific. I am using MinGW (gcc 3.4.5).

Thanks in advance.

Was it helpful?

Solution

I think you need to take a look at win32 console functions for example GetStdHandle(), ReadConsoleOutput(), WriteConsoleOutput etc.

OTHER TIPS

In Win32, ReadConsoleOutput:

Reads character and color attribute data from a rectangular block of character cells in a console screen buffer, and the function writes the data to a rectangular block at a specified location in the destination buffer.

Download mingw-readline

And look GNU Readline

rl_line_buffer

If it's the screen in a command window, then potentially no, or no easy way. You could hack at Windows events to select-all, copy, and read the clipboard.

Here's a way to read the console buffer. GetNumCharsInConsoleBuffer is to get the total characters written in the console screen buffer, I use GetConsoleScreenBufferInfo inside. After, I create a dynamically allocated array of size equal to the previously value returned by GetNumCharsInConsoleBuffer + 1 (for zero-ending). And finally, ReadConsoleBuffer will fill the buffer just created with the contents of the console screen buffer. After, if you want to write the contents of your buffer to a file, you'll probably need to do some formatting. With ReadConsoleOutputCharacter you get a region(rectangle) of the console screen buffer. The lines you wrote to the console screen buffer will be padded with spaces to fit the region of the buffer. it'll be the same with the win32 ReadConsoleOutput/WriteConsoleOutput, you'll get a region(rectangle) of your screen.

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

Output:

Writting
in
the
buffer
Buffer contents:
Writting
in
the
buffer

Appuyez sur une touche pour continuer...

EDIT:

I just wrote a function that can be used to write the contents of the screen buffer to file. This function removes the padded spaces from the screen console buffer. ReadConsoleBuffer takes a null char pointer as first argument (buffer) that will be allocated during its execution. So don't forget to delete it by yourself. ReadConsoleBuffer will write the size of the buffer in the second argument (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;
}

Output in 'out.txt':

Writting
in
the
buffer
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top