Windows Sandbox中Desktop Duplication API返回空白图像问题
Windows Sandbox屏幕录制异常问题
基于dotnet-window-capture项目实现Windows Sandbox屏幕录制,原代码如下:
var hr = _duplication.TryAcquireNextFrame(100, out _, out var desktopResourceOut); if (hr.Failure) return null; using var desktopTexture = desktopResourceOut.QueryInterface<Texture2D>(); var texture2dDescription = new Texture2DDescription { ArraySize = 1, BindFlags = BindFlags.ShaderResource | BindFlags.RenderTarget, CpuAccessFlags = CpuAccessFlags.None, Format = Format.B8G8R8A8_UNorm, Height = desktopTexture.Description.Height, MipLevels = 1, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default, Width = desktopTexture.Description.Width }; var texture2d = new Texture2D(device, texture2dDescription); device.ImmediateContext.CopyResource(desktopTexture, texture2d); // release resources desktopResourceOut.Dispose(); _duplication.ReleaseFrame(); return texture2d;
该代码在本地机器及RDP环境下可正常运行,但在Windows Sandbox中始终返回空白窗口。
排查与修改过程
原代码存在两处不足:
- 未处理
TryAcquireNextFrame的所有失败情况 - 忽略
OutputDuplicateFrameInformation,未检查LastPresentTime(虽与MSDN文档描述矛盾,但有相关讨论指出需检查)
完善错误处理及OutputDuplicateFrameInformation检查后,Windows Sandbox中出现以下现象:
- 移动鼠标时
TryAcquireNextFrame大多成功,但OutputDuplicateFrameInformation.LastPresentTime始终为0 - 仅出现错误码
0x887A0027(超时,提示无画面更新需等待) - 忽略
LastPresentTime==0时,texture2d为黑色 - 尝试复制desktopTexture的
Texture2DDescription参数以避免CopyResource静默失败,无效果 - 枚举适配器及输出后确认系统仅存在一个Output
最终修改后的代码仍返回空白texture2d:
var hr = _duplication.TryAcquireNextFrame(100, out var frameInfo, out var desktopResourceOut); if (hr.Failure) { if (hr.Code == unchecked((int)0x887A0027)) return null; // no changes hr.CheckError(); return null; } try { //if (frameInfo.LastPresentTime == 0) { // return null; // in Sandbox all frames go here //} using var desktopTexture = desktopResourceOut.QueryInterface<Texture2D>(); var texture2dDescription = new Texture2DDescription { ArraySize = desktopTexture.Description.ArraySize, BindFlags = BindFlags.ShaderResource | BindFlags.RenderTarget, CpuAccessFlags = CpuAccessFlags.None, Format = desktopTexture.Description.Format, Height = desktopTexture.Description.Height, MipLevels = 1, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default, Width = desktopTexture.Description.Width }; var texture2d = new Texture2D(device, texture2dDescription); device.ImmediateContext.CopyResource(desktopTexture, texture2d); return texture2d; } finally { // release resources desktopResourceOut.Dispose(); _duplication.ReleaseFrame(); }
替代方案尝试
尝试使用WinRT的IGraphicsCaptureItemInterop::CreateForMonitor(hmon, new Guid("79C3F95B-31F7-4EC2-A464-632EF5D30760"))作为替代方案,但失败并返回错误码0x80040154(REGDB_E_CLASSNOTREG)。
内容的提问来源于stack exchange,提问作者LOST
相关产品推荐
相关产品推荐

