Closed khaled-benahmed closed 1 year ago
Hey, do you have a simple code snipped to reproduce this error?
You're trying to use a new captures service for each capture without freeing the resource of the previous which is not supported since the second time (and all following) it can't access the device.
Two ways to fix this:
Thank you for your response. I understand now that I should dispose the DX11ScreenCaptureService after I'm done using it. However, I'm not sure how to implement this logic in my code because if I dispose the service before calling GetScreenshot method, it will return nothing. Additionally, since I'm calling the method in a loop, I can't put the configuration code inside the method. Would it be possible for you to provide some guidance on how to properly dispose the service in this scenario?
That's correct, as soon as you dispose the service it can't be used anymore. But I can't really help since it all depends on how you manage the lifetime of your objects.
Okey ..Thank you very much for your helpful informations
The following code can capture the current screen every 1 second. Hope it can be helpful.
using ScreenCapture.NET;
namespace ConsoleApp1
{
internal class Program
{
static void CaptureAndSaveScreen(string filePath, IScreenCapture screenCapture)
{
ICaptureZone fullscreen = screenCapture.RegisterCaptureZone(0, 0, screenCapture.Display.Width, screenCapture.Display.Height);
screenCapture.CaptureScreen();
using (fullscreen.Lock())
{
IImage image = fullscreen.Image;
var imageSharp = new SixLabors.ImageSharp.Image<Rgba32>(image.Width, image.Height);
for (int y = 0; y < image.Height; y++)
{
for (int x = 0; x < image.Width; x++)
{
IColor color = image[x, y];
imageSharp[x, y] = new Rgba32(color.R, color.G, color.B, color.A);
}
}
imageSharp.Save(filePath);
}
}
static void Main(string[] args)
{
IScreenCaptureService screenCaptureService = new DX11ScreenCaptureService();
IEnumerable<GraphicsCard> graphicsCards = screenCaptureService.GetGraphicsCards();
IEnumerable<Display> displays = screenCaptureService.GetDisplays(graphicsCards.First());
IScreenCapture screenCapture = screenCaptureService.GetScreenCapture(displays.First());
var timer = new System.Timers.Timer(1000);
timer.Elapsed += (sender, e) => CaptureAndSaveScreen($"screenshot_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}.png", screenCapture);
timer.Start();
Console.WriteLine("Press any key to stop...");
Console.ReadKey();
timer.Stop();
}
}
}
NuGet
SixLabors.ImageSharp
ScreenCapture.NET
ScreenCapture.NET.DX11
@azpanel Be careful here, this will leak massive amounts of memory! Registering the CaptureZone should be part of the initialization and happen only once.
For fullscreen capturing you could also simplify the ImageSharp-Image creation since it's save to assume that the DX11 capture always contains BGRA32-data.
static void CaptureAndSaveScreen(string filePath, IScreenCapture screenCapture, ICaptureZone captureZone)
{
screenCapture.CaptureScreen();
using (captureZone.Lock())
{
SixLabors.ImageSharp.Image<Bgra32> image = Image.LoadPixelData<Bgra32>(captureZone.RawBuffer, captureZone.Width, captureZone.Height);
image.Save(filePath);
}
}
Message=Object reference not set to an instance of an object. Source=SharpGen.Runtime Arborescence des appels de procédure : à SharpGen.Runtime.CppObject.get_Item(Int32 index) à Vortice.Direct3D11.ID3D11Device.CreateTexture2D(Texture2DDescription desc, Void* initialData) à Vortice.Direct3D11.ID3D11Device.CreateTexture2D(Texture2DDescription description, SubresourceData[] initialData) à ScreenCapture.NET.DX11ScreenCapture.InitializeCaptureZone(CaptureZone& captureZone) à ScreenCapture.NET.DX11ScreenCapture.RegisterCaptureZone(Int32 x, Int32 y, Int32 width, Int32 height, Int32 downscaleLevel)
CaptureZone fullscreen = screenCapture.RegisterCaptureZone(0, 0, screenCapture.Display.Width, screenCapture.Display.Height);