using Microsoft.Extensions.Logging; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; namespace RmmAgent.Services; #pragma warning disable CA1416 public class ScreenshotService { private readonly ILogger _logger; private readonly ApiClient _api; public ScreenshotService(ILogger logger, ApiClient api) { _logger = logger; _api = api; } public async Task CaptureAndUploadAsync(CancellationToken ct) { var (jpegBytes, width, height) = CaptureJpeg(); if (jpegBytes is null) return; try { await _api.UploadScreenshotAsync(jpegBytes, width, height, ct); _logger.LogDebug("Screenshot uploaded: {Size} bytes ({W}x{H})", jpegBytes.Length, width, height); } catch (Exception ex) { _logger.LogWarning(ex, "Screenshot upload failed"); throw; } } [DllImport("user32.dll")] private static extern int GetSystemMetrics(int nIndex); private const int SM_XVIRTUALSCREEN = 76; private const int SM_YVIRTUALSCREEN = 77; private const int SM_CXVIRTUALSCREEN = 78; private const int SM_CYVIRTUALSCREEN = 79; private (byte[]? bytes, int width, int height) CaptureJpeg() { try { int x = GetSystemMetrics(SM_XVIRTUALSCREEN); int y = GetSystemMetrics(SM_YVIRTUALSCREEN); int w = GetSystemMetrics(SM_CXVIRTUALSCREEN); int h = GetSystemMetrics(SM_CYVIRTUALSCREEN); if (w <= 0 || h <= 0) { w = 1920; h = 1080; } using var bmp = new Bitmap(w, h, PixelFormat.Format32bppArgb); using (var g = Graphics.FromImage(bmp)) g.CopyFromScreen(x, y, 0, 0, new Size(w, h), CopyPixelOperation.SourceCopy); // Downscale (économise bande passante mutualisé) int targetW = Math.Min(1600, w); int targetH = h * targetW / w; using var resized = new Bitmap(targetW, targetH); using (var g = Graphics.FromImage(resized)) { g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.DrawImage(bmp, 0, 0, targetW, targetH); } using var ms = new MemoryStream(); var jpegEncoder = ImageCodecInfo.GetImageEncoders().FirstOrDefault(c => c.FormatID == ImageFormat.Jpeg.Guid); if (jpegEncoder is null) return (null, 0, 0); var encParams = new EncoderParameters(1); encParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 60L); resized.Save(ms, jpegEncoder, encParams); return (ms.ToArray(), targetW, targetH); } catch (Exception ex) { _logger.LogWarning(ex, "Screen capture failed"); return (null, 0, 0); } } }