【问题标题】:SetConsoleActiveScreenBuffer does not display screen bufferSetConsoleActiveScreenBuffer 不显示屏幕缓冲区
【发布时间】:2017-01-19 11:30:52
【问题描述】:

我目前正在尝试用 C# 编写一个带有两个屏幕缓冲区的控制台应用程序,它们应该来回交换(很像现代 GPU 上的 VSync)。由于System.Console 类没有提供切换缓冲区的方法,我不得不从 kernel32.dll 中 P/Invoke 几个方法。

这是我当前的代码,非常简化:

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 */

    SetConsoleActiveScreenBuffer(newBuffer);
}

发生了以下事情:

  • 屏幕仍然是空的,尽管它应该显示newBuffer
  • 当写入oldBuffer 而不是newBuffer 时,数据会立即出现。因此,我写入缓冲区的方式应该是正确的。
  • 在调用SetConsoleActiveScreenBuffer(newBuffer) 时,错误代码现在为6,表示句柄无效。这很奇怪,因为句柄不是 -1,文档将其描述为无效。

我应该注意,我很少直接使用 Win32 API,并且对常见的 Win32 相关问题了解甚少。我将不胜感激。

【问题讨论】:

  • 请勿致电GetLastError,除非明确要求这样做。有关更多信息,请参阅此documentation。阅读完毕后,更新您的问题。
  • 好吧,但这并没有真正改变整个问题太多。重点是设置缓冲区不起作用,我不明白为什么。
  • 您至少可以从 “发生的事情” 列表中删除多余的观察结果。明确指出观察到的行为与记录的行为匹配没有任何价值。
  • 我删除了关于获取当前控制台缓冲区的一项,但我保留了第二项,因为我相信那里的调用会失败
  • 它失败了,因为你传入了一个无效的句柄。您没有检查 CreateConsoleScreenBuffer 的返回值,并且为 dwDesiredAccess 传递 0 似乎不正确。

标签: c# winapi console-application


【解决方案1】:

正如 IInspectable 在 cmets 中指出的那样,您将 dwDesiredAccess 设置为零。这为您提供了一个没有访问权限的句柄。在某些极端情况下,这样的句柄很有用,但这不是其中之一。

唯一有点奇怪的是您得到的是“无效句柄”而不是“访问被拒绝”。我猜你正在运行 Windows 7,所以句柄是用户模式对象(“伪句柄”)而不是内核句柄。

无论如何,您需要将dwDesiredAccess 设置为GENERIC_READ | GENERIC_WRITE,如图所示in the sample code


此外,正如 Hans 在 cmets 中指出的那样,pinvoke.net 上的声明是不正确的,将最后一个参数指定为四字节整数而不是指针大小的整数。我相信正确的声明是

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

【讨论】:

  • [DllImport] 声明也不正确,最后一个参数是 IntPtr。
  • 这很可能是pinvoke.net上的代码造成的,这无疑是错误的。
  • @CodeCaster 是的。我看到这里有几个人提到 pinvoke.net,所以我认为它有一定的可信度
  • 我在 pinvoke.net 上编辑了页面,希望我做对了。 :-)
猜你喜欢
  • 2013-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多