如何在LocalSystem权限的Session 0服务中获取主显示IDXGIOutput
远程访问应用Session 0环境下获取IDXGIOutput的问题
背景与需求
我开发了一款远程访问应用,采用IDXGIOutputDuplication捕获主显示画面,核心依赖获取显示设备的IDXGIOutput。这套代码在Visual Studio调试环境下运行正常,但将其作为LocalSystem权限的Session 0服务运行时,EnumOutputs()调用失效。
由于应用需要始终在线,且必须捕获登录页面、UAC提示等安全桌面内容,必须以LocalSystem权限的Session 0服务形式部署。根据官方文档,Session 0服务中使用IDXGIOutputDuplication是受支持的场景,现需解决如何在此环境下正确获取主显示的IDXGIOutput,以正常调用DuplicateOutput()。
原始实现代码
// intermediate variables for casting IDXGIOutput* pDisplay_old; IDXGIFactory1* pFactory; IDXGIAdapter* pGPU; ID3D11Device* pD3D; ID3D11DeviceContext* pD3DContext; IDXGIOutput1* pDisplay; // create DXGI factory res = CreateDXGIFactory1(IID_PPV_ARGS(&pFactory)); if (FAILED(res)) { cerr << "CreateDXGIFactory1 " << res; return 1; } // get GPU adapter res = pFactory->EnumAdapters(0, &pGPU); if (FAILED(res)) { cerr << "EnumAdapters " << res; return 1; } // create D3D11 device res = D3D11CreateDevice(pGPU, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &pD3D, NULL, &pD3DContext); if (FAILED(res)) { cerr << "D3D11CreateDevice " << res; return 1; } // get display res = pGPU->EnumOutputs(0, &pDisplay_old); if (FAILED(res)) { cerr << "EnumOutputs " << res; return 1; } res = pDisplay_old->QueryInterface(&pDisplay); if (FAILED(res)) { cerr << "QueryInterface " << res; return 1; } // free resources pDisplay_old->Release(); pGPU->Release(); pFactory->Release();
尝试的解决方法及新问题
为适配Session 0环境,我在代码开头添加了桌面上下文切换的逻辑:
// Assigns the specified desktop to the calling thread HDESK currentInputDesktop = OpenInputDesktop(0, false, GENERIC_ALL); if (currentInputDesktop == NULL) { cerr << "OpenInputDesktop " << GetLastError(); return 1; } res = SetThreadDesktop(currentInputDesktop); if (res == 0) { cerr << "SetThreadDesktop " << GetLastError(); return 1; } CloseDesktop(currentInputDesktop);
使用psexec -s -h以LocalSystem权限运行代码时,OpenInputDesktop调用失败,GetLastError()返回值为1(对应ERROR_INVALID_FUNCTION),无法定位问题原因。
内容的提问来源于stack exchange,提问作者Tiger Yang
相关产品推荐
相关产品推荐

