Снимок экрана дублирования рабочего стола - DuplicateOutput возвращает ошибку E_ACCESSDENIED

Я снимаю экраны с помощью API дублирования рабочего стола (DirectX11). DuplicateOutput API возвращает ошибку отказа в доступе, и это тоже происходит очень редко (может быть в 10% случаев) на компьютере с Windows 8.1 на экране входа в систему, хотя мое приложение работает с привилегиями уровня 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, Подробно: доступ запрещен.

0 ответов

Другие вопросы по тегам