返回

OpenGL DLL 中的桌面复制 API 调用遇到 ERROR_BUSY 错误?如何解决?

windows

在 OpenGL 应用程序的 DLL 中安全调用桌面复制 API

问题陈述

在 OpenGL 应用程序的动态链接库(DLL)中,SetThreadDesktop 函数调用失败,并返回错误代码 "ERROR_BUSY" (170)。这表示该请求的资源(桌面)正在使用中。

原因分析

此错误通常是由于以下原因引起的:

  • 另一个线程正在使用相同的桌面。
  • 该线程已经有一个关联的桌面。

解决方法

为了解决此问题,建议采取以下步骤:

  1. 检查线程是否繁忙 :确保没有其他线程正在使用要复制的桌面。
  2. 检查线程是否已关联桌面 :确保该线程尚未附加到其他桌面。
  3. 使用 "OpenInputDesktop(NULL, FALSE, GENERIC_ALL)" :获取桌面句柄时,使用 "OpenInputDesktop(NULL, FALSE, GENERIC_ALL)" 而不是 "OpenInputDesktop(0, FALSE, GENERIC_ALL)"。
  4. 调用 "SetThreadDesktop" 之前关闭桌面句柄 :在调用 "SetThreadDesktop" 之前,关闭桌面句柄("CloseDesktop(hDesk)")。
  5. 检查 "SetThreadDesktop" 的返回值 :确保 "SetThreadDesktop" 成功返回,否则返回错误消息。

示例代码

以下是修改后的 DLL 代码示例:

    // Get desktop
    HDESK hDesk = OpenInputDesktop(NULL, FALSE, GENERIC_ALL);
    if (!hDesk)
        return "Failed to open desktop";

    // Close desktop handle before setting thread desktop
    CloseDesktop(hDesk);

    // Attach desktop to this thread
    bool deskAttached = SetThreadDesktop(NULL) != 0;
    if (!deskAttached)
        return "Failed to attach recording thread to desktop";

其他注意事项

  • 以管理员身份运行应用程序。
  • 如果问题仍然存在,请查阅桌面复制 API 文档,以获取其他潜在原因。

常见问题解答

1. 我尝试了所有步骤,但仍然收到 "ERROR_BUSY" 错误。

  • 确保另一个线程确实没有使用要复制的桌面。
  • 检查线程是否与任何其他桌面关联。

2. 为什么调用 "OpenInputDesktop(NULL, FALSE, GENERIC_ALL)" 而不是 "OpenInputDesktop(0, FALSE, GENERIC_ALL)" 很重要?

  • "0" 是当前线程的会话 ID,这可能导致在某些情况下出现死锁。

3. 为什么需要在调用 "SetThreadDesktop" 之前关闭桌面句柄?

  • 保持对桌面句柄的开放引用可能会导致桌面处于活动状态并阻止对其进行复制。

4. 我该如何检查 "SetThreadDesktop" 的返回值?

  • 检查函数的返回值是否为非零。如果为零,则该函数调用失败。

5. 我需要在 DLL 中对 SetThreadDesktop 做什么其他检查吗?

  • 考虑检查线程是否属于当前进程。调用 "GetCurrentThreadId" 和 "GetCurrentProcessId" 来获取线程和进程 ID,然后将其与 "GetThreadDesktop" 和 "GetWindowThreadProcessId" 的返回值进行比较。