我正在使用桌面复制 API (DirectX11) 捕获屏幕。DuplicateOutput API 返回访问被拒绝错误,这在登录屏幕上的 Windows 8.1 机器上也非常罕见(可能是 10% 的时间),尽管我的应用程序以 SYSTEM 级别权限运行并且 SetThreadDesktop 被正确调用。我曾经在遇到每个错误后都重置并调用 SetThreadDesktop,但即使在多次设备重置和初始化之后,应用程序也无法从错误中恢复。在多次重试或重新启动应用程序后,我不得不回退到基于 GDI(从 directx 切换到 GDI 后应用程序工作正常)的方法,但这个想法似乎很糟糕。
注意:我确实在 Windows 10/Windows 8 机器上遇到了同样的问题,但与特定的 Windows 8.1 机器相比并不常见。
这是 E_ACCESSDENIED 错误的描述,它仅说明此错误的可能情况(没有系统级权限或未正确调用 SetThreadDesktop)。我尝试了所有可能的方法来找出问题,但不能。
任何帮助将不胜感激,在此先感谢。
下面是初始化设备的代码:
//
// Initialize duplication interfaces
//
HRESULT cDuplicationManager::InitDupl(_In_ ID3D11Device* Device, _In_ IDXGIAdapter *_pAdapter, _In_ IDXGIOutput *_pOutput, _In_ UINT Output)
{
HRESULT hr = E_FAIL;
if(!_pOutput || !_pAdapter || !Device)
{
return hr;
}
m_OutputNumber = Output;
// Take a reference on the device
m_Device = Device;
m_Device->AddRef();
_pOutput->GetDesc(&m_OutputDesc);
// QI for Output 1
IDXGIOutput1* DxgiOutput1 = nullptr;
hr = _pOutput->QueryInterface(__uuidof(DxgiOutput1), reinterpret_cast<void**>(&DxgiOutput1));
if (FAILED(hr))
{
return ProcessFailure(nullptr, _T("Failed to QI for DxgiOutput1 in DUPLICATIONMANAGER"), _T("Error"), hr);
}
// Create desktop duplication
hr = DxgiOutput1->DuplicateOutput(m_Device, &m_DeskDupl);
DxgiOutput1->Release();
DxgiOutput1 = nullptr;
if (FAILED(hr) || !m_DeskDupl)
{
if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
{
return ProcessFailure(nullptr, _T("Maximum number of applications using Desktop Duplication API"), _T("Error"), hr);
}
return ProcessFailure(m_Device, _T("Failed to get duplicate output in DUPLICATIONMANAGER"), _T("Error"), hr);//, CreateDuplicationExpectedErrors);
}
return S_OK;
}
将桌面设置为当前线程的代码:
DWORD setCurrentInputDesktop()
{
DWORD errorCode = ERROR_ACCESS_DENIED;
HDESK currentInputDesktop = OpenInputDesktop(0, false, GENERIC_ALL);
if(currentInputDesktop != NULL)
{
if(!SetThreadDesktop(currentInputDesktop))
{
errorCode = GetLastError();
cout << ("setCurrentInputDesktop: SetThreadDesktop failed. Error code: ") << errorCode;
}
else
{
errorCode = ERROR_SUCCESS;
cout << ("setCurrentInputDesktop: SetThreadDesktop succeeded.");
}
CloseDesktop(currentInputDesktop);
}
else
{
errorCode = GetLastError();
cout << "setCurrentInputDesktop: OpenInputDesktop failed. Error code: " << errorCode;
}
return errorCode;
}
以下是处理错误码后返回的错误信息:
Id3d11DuplicationManager::ProcessFailure - 错误:无法在 DUPLICATIONMANAGER 中获取重复输出,详细信息:访问被拒绝。