デスクトップ複製 API (DirectX11) を使用して画面をキャプチャしています。DuplicateOutput API はアクセス拒否エラーを返します。アプリケーションが SYSTEM レベルの権限で実行され、SetThreadDesktop が適切に呼び出されているにもかかわらず、ログオン画面の Windows 8.1 マシンでも非常にまれに (10% の確率で) 発生します。エラーが発生するたびにリセットして 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 で重複した出力を取得できませんでした。詳細: アクセスが拒否されました。