MechMK1 MechMK1 - 11 months ago 84
C# Question

SetConsoleActiveScreenBuffer does not display screen buffer

I am currently trying to write a console application in C# with two screen buffers, which should be swapped back and forth (much like VSync on a modern GPU). Since the

class does not provide a way to switch buffers, I had to P/Invoke several methods from kernel32.dll.

This is my current code, grossly simplified:

static void Main(string[] args)
IntPtr oldBuffer = GetStdHandle(-11); //Gets the handle for the default console buffer
IntPtr newBuffer = CreateConsoleScreenBuffer(0, 0x00000001, IntPtr.Zero, 1, 0); //Creates a new console buffer

/* Write data to newBuffer */


The following things occured:

  • The screen remains empty, even though it should be displaying

  • When written to
    instead of
    , the data appears immediately. Thus, my way of writing into the buffer should be correct.

  • Upon calling
    , the error code is now 6, which means invalid handle. This is strange, as the handle is not -1, which the documentation discribes as invalid.

I should note that I very rarely worked with the Win32 API directly and have very little understanding of common Win32-related problems. I would appreciate any sort of help.

Answer Source

As IInspectable points out in the comments, you're setting dwDesiredAccess to zero. That gives you a handle with no access permissions. There are some edge cases where such a handle is useful, but this isn't one of them.

The only slight oddity is that you're getting "invalid handle" rather than "access denied". I'm guessing you're running Windows 7, so the handle is a user-mode object (a "pseudohandle") rather than a kernel handle.

At any rate, you need to set dwDesiredAccess to GENERIC_READ | GENERIC_WRITE as shown in the sample code.

Also, as Hans pointed out in the comments, the declaration on was incorrect, specifying the last argument as a four-byte integer rather than a pointer-sized integer. I believe the correct declaration is

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateConsoleScreenBuffer(
    uint dwDesiredAccess,
    uint dwShareMode, 
    IntPtr lpSecurityAttributes, 
    uint dwFlags,
    IntPtr lpScreenBufferData