Reputation: 3250
I am fiddling with recording the screen of Windows Sandbox based on https://github.com/mika-f/dotnet-window-capture :
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;
Problem is from the start the code works on my own machine and also via RDP. But inside the Windows Sandbox all I get is a blank window.
Now I searched around, and found a few "deficiencies" in the above sample, namely:
TryAcquireNextFrame
are ignored silently.OutputDuplicateFrameInformation
is ignored. Specifically, it never checks LastPresentTime
which must be checked according to this SO thread (although that contradicts When AcquireNextFrame returns successfully, the calling application can access the desktop image that AcquireNextFrame returns in the variable at ppDesktopResource
from MSDN).So after fiddling with error handling and OutputDuplicateFrameInformation
all I am getting from Windows Sandbox is:
TryAcquireNextFrame
mostly succeeds, however OutputDuplicateFrameInformation.LastPresentTime
is always 0.0x887A0027
aka timeout, which just indicates the need to wait more as there was no picture update.LastPresentTime == 0
, the texture2d
comes out black.Texture2DDescription
parameters directly from desktopTexture
in attempt to avoid potential silent failure of CopyResource
as suggested in this SO thread, but that had no visible effect.The final modification that still exhibits the blank texture2d
behavior is
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();
}
P.S. As alternative I also tried WinRT's IGraphicsCaptureItemInterop::CreateForMonitor(hmon, new Guid("79C3F95B-31F7-4EC2-A464-632EF5D30760"))
but this one fails with 0x80040154 REGDB_E_CLASSNOTREG
.
Upvotes: 0
Views: 428