diff --git a/Desktop.Core/Services/ScreenCaster.cs b/Desktop.Core/Services/ScreenCaster.cs index 0fddb46d..dfa786b9 100644 --- a/Desktop.Core/Services/ScreenCaster.cs +++ b/Desktop.Core/Services/ScreenCaster.cs @@ -42,17 +42,15 @@ namespace Remotely.Desktop.Core.Services _shutdownService = shutdownService; } - public void BeginScreenCasting(ScreenCastRequest screenCastRequest) { - _ = Task.Run(async () => await CastScreen(screenCastRequest)); + _ = Task.Run(() => BeginScreenCastingImpl(screenCastRequest)); } - private async Task CastScreen(ScreenCastRequest screenCastRequest) + private async Task BeginScreenCastingImpl(ScreenCastRequest screenCastRequest) { try { - long sequence = 0; var viewer = ServiceContainer.Instance.GetRequiredService(); viewer.Name = screenCastRequest.RequesterName; viewer.ViewerConnectionID = screenCastRequest.ViewerID; @@ -121,6 +119,19 @@ namespace Remotely.Desktop.Core.Services return; } + _ = Task.Run(() => CastScreen(screenCastRequest, viewer, 0)); + } + catch (Exception ex) + { + Logger.Write(ex); + } + } + + private async Task CastScreen(ScreenCastRequest screenCastRequest, Viewer viewer, int sequence) + { + try + { + while (!viewer.DisconnectRequested && viewer.IsConnected) { try @@ -142,11 +153,12 @@ namespace Remotely.Desktop.Core.Services viewer.ApplyAutoQuality(); - result = viewer.Capturer.GetNextFrame(); + var result = viewer.Capturer.GetNextFrame(); if (!result.IsSuccess || result.Value is null) { - continue; + _ = Task.Run(() => CastScreen(screenCastRequest, viewer, sequence)); + return; } var diffArea = viewer.Capturer.GetFrameDiffArea(); diff --git a/Desktop.Win/Services/ScreenCapturerWin.cs b/Desktop.Win/Services/ScreenCapturerWin.cs index 2831a9d7..96bad186 100644 --- a/Desktop.Win/Services/ScreenCapturerWin.cs +++ b/Desktop.Win/Services/ScreenCapturerWin.cs @@ -42,6 +42,7 @@ using Result = Remotely.Shared.Result; using SkiaSharp; using SkiaSharp.Views.Desktop; using Remotely.Desktop.Core.Extensions; +using System.Runtime.InteropServices; namespace Remotely.Desktop.Win.Services { @@ -97,7 +98,17 @@ namespace Remotely.Desktop.Win.Services { try { - Win32Interop.SwitchToInputDesktop(); + if (!Win32Interop.SwitchToInputDesktop()) + { + // Something will occasionally prevent this from succeeding after active + // desktop has changed to/from WinLogon (err code 170). I'm guessing a hook + // is getting put in the desktop, which causes SetThreadDesktop to fail. + // The caller can start a new thread, which seems to resolve it. + var errCode = Marshal.GetLastWin32Error(); + var errMessage = $"Failed to switch to input desktop. Last Win32 error code: {errCode}"; + Logger.Write(errMessage); + return Result.Fail(errMessage); + } if (NeedsInit) {