diff --git a/Remotely_Agent/Resources/Remotely_ScreenCapture.exe b/Remotely_Agent/Resources/Remotely_ScreenCapture.exe index 3f7f2196..9e29f50e 100644 Binary files a/Remotely_Agent/Resources/Remotely_ScreenCapture.exe and b/Remotely_Agent/Resources/Remotely_ScreenCapture.exe differ diff --git a/Remotely_Agent/Services/ClientSocket.cs b/Remotely_Agent/Services/ClientSocket.cs index 00eac05c..f7c6dd1c 100644 --- a/Remotely_Agent/Services/ClientSocket.cs +++ b/Remotely_Agent/Services/ClientSocket.cs @@ -26,12 +26,7 @@ namespace Remotely_Agent.Services ConnectionInfo = Utilities.GetConnectionInfo(); HubConnection = new HubConnectionBuilder() - .WithUrl(ConnectionInfo.Host + "/DeviceHub", options=> { - if (!string.IsNullOrWhiteSpace(ConnectionInfo.ProxyUrl)) - { - options.Proxy = new WebProxy(ConnectionInfo.ProxyUrl, ConnectionInfo.ProxyPort); - } - }) + .WithUrl(ConnectionInfo.Host + "/DeviceHub") .Build(); HubConnection.Closed += HubConn_Closed; @@ -160,7 +155,7 @@ namespace Remotely_Agent.Services return; } // Cleanup old files. - foreach (var file in Directory.GetFiles(Path.GetTempPath(), "Remotely_ScreenCast")) + foreach (var file in Directory.GetFiles(Path.GetTempPath(), "Remotely_ScreenCast*")) { try { @@ -192,7 +187,7 @@ namespace Remotely_Agent.Services if (OSUtils.IsWindows) { #if DEBUG - Process.Start(filePath); + Process.Start(filePath, $"-mode unattended -requester {requesterID} -serviceid {serviceID} -hostname {Utilities.GetConnectionInfo().Host.Split("//").Last()}"); #else var procInfo = new ADVAPI32.PROCESS_INFORMATION(); var result = Win32Interop.OpenInteractiveProcess(filePath + $" -mode unattended -requester {requesterID} -serviceid {serviceID} -hostname {Utilities.GetConnectionInfo().Host.Split("//").Last()}", "default", true, out procInfo); diff --git a/Remotely_Library/Models/ConnectionInfo.cs b/Remotely_Library/Models/ConnectionInfo.cs index 6a297025..3d075391 100644 --- a/Remotely_Library/Models/ConnectionInfo.cs +++ b/Remotely_Library/Models/ConnectionInfo.cs @@ -24,8 +24,6 @@ namespace Remotely_Library.Models } } public string OrganizationID { get; set; } - public string ProxyUrl { get; set; } - public int ProxyPort { get; set; } public string ServerVerificationToken { get; set; } } } diff --git a/Remotely_ScreenCast/BitBltCapture.cs b/Remotely_ScreenCast/Capture/BitBltCapture.cs similarity index 85% rename from Remotely_ScreenCast/BitBltCapture.cs rename to Remotely_ScreenCast/Capture/BitBltCapture.cs index 99397f5f..53597fb5 100644 --- a/Remotely_ScreenCast/BitBltCapture.cs +++ b/Remotely_ScreenCast/Capture/BitBltCapture.cs @@ -12,16 +12,25 @@ using System.Collections.Generic; using System.Drawing.Drawing2D; using System.Diagnostics; using System.Runtime.Serialization.Formatters.Binary; +using Remotely_ScreenCapture.Utilities; -namespace Remotely_ScreenCast +namespace Remotely_ScreenCast.Capture { public class BitBltCapture : ICapturer { public Bitmap CurrentFrame { get; set; } + public Size CurrentScreenSize + { + get + { + return CurrentBounds.Size; + } + } public Bitmap PreviousFrame { get; set; } public bool IsCapturing { get; set; } public bool CaptureFullscreen { get; set; } = true; public int PauseForMilliseconds { get; set; } + public EventHandler ScreenChanged { get; set; } public int SelectedScreen { get @@ -30,6 +39,10 @@ namespace Remotely_ScreenCast } set { + if (value == selectedScreen) + { + return; + } if (Screen.AllScreens.Length >= value + 1) { selectedScreen = value; @@ -39,6 +52,7 @@ namespace Remotely_ScreenCast selectedScreen = 0; } CurrentBounds = Screen.AllScreens[selectedScreen].Bounds; + ScreenChanged(this, CurrentBounds.Size); } } public Rectangle CurrentBounds { get; set; } = Screen.PrimaryScreen.Bounds; @@ -80,7 +94,7 @@ namespace Remotely_ScreenCast public void Capture() { - Console.WriteLine($"Using Capturer."); + Console.WriteLine($"Using BitBlt Capturer."); var currentDesktop = Win32Interop.GetCurrentDesktop(); Console.WriteLine($"Current Desktop: {currentDesktop}"); if (currentDesktop != desktopName) @@ -89,7 +103,7 @@ namespace Remotely_ScreenCast var inputDesktop = Win32Interop.OpenInputDesktop(); var success = User32.SetThreadDesktop(inputDesktop); User32.CloseDesktop(inputDesktop); - Console.WriteLine($"Set thread desktop: {success}"); + Logger.Write($"Set thread desktop: {success}"); } @@ -101,7 +115,7 @@ namespace Remotely_ScreenCast } catch (Exception ex) { - //Utilities.WriteToLog(ex); + Logger.Write(ex); } } diff --git a/Remotely_ScreenCast/Capture/CaptureMode.cs b/Remotely_ScreenCast/Capture/CaptureMode.cs new file mode 100644 index 00000000..5d0ec169 --- /dev/null +++ b/Remotely_ScreenCast/Capture/CaptureMode.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Remotely_ScreenCapture.Capture +{ + public enum CaptureMode + { + BitBtl, + DirectX + } +} diff --git a/Remotely_ScreenCast/CursorIconWatcher.cs b/Remotely_ScreenCast/Capture/CursorIconWatcher.cs similarity index 97% rename from Remotely_ScreenCast/CursorIconWatcher.cs rename to Remotely_ScreenCast/Capture/CursorIconWatcher.cs index 958e81f5..87986f38 100644 --- a/Remotely_ScreenCast/CursorIconWatcher.cs +++ b/Remotely_ScreenCast/Capture/CursorIconWatcher.cs @@ -9,7 +9,7 @@ using System.Timers; using System.Windows.Forms; using Win32; -namespace Remotely_ScreenCast +namespace Remotely_ScreenCast.Capture { /// /// A class that can be used to watch for cursor icon changes. diff --git a/Remotely_ScreenCast/DXCapture.cs b/Remotely_ScreenCast/Capture/DXCapture.cs similarity index 85% rename from Remotely_ScreenCast/DXCapture.cs rename to Remotely_ScreenCast/Capture/DXCapture.cs index b39d6a55..b5107408 100644 --- a/Remotely_ScreenCast/DXCapture.cs +++ b/Remotely_ScreenCast/Capture/DXCapture.cs @@ -1,4 +1,5 @@ -using SharpDX; +using Remotely_ScreenCapture.Utilities; +using SharpDX; using SharpDX.Direct3D11; using SharpDX.DXGI; using SharpDX.Mathematics.Interop; @@ -14,7 +15,7 @@ using System.Threading; using System.Threading.Tasks; using Win32; -namespace Remotely_ScreenCast +namespace Remotely_ScreenCast.Capture { public class DXCapture : ICapturer { @@ -22,10 +23,17 @@ namespace Remotely_ScreenCast { Init(); } - public Bitmap PreviousFrame { get; set; } public Bitmap CurrentFrame { get; set; } + public Size CurrentScreenSize + { + get + { + return new Size(width, height); + } + } public bool CaptureFullscreen { get; set; } = true; + public EventHandler ScreenChanged { get; set; } public int SelectedScreen { get @@ -34,6 +42,10 @@ namespace Remotely_ScreenCast } set { + if (value == selectedScreen) + { + return; + } if (adapter == null) { selectedScreen = 0; @@ -48,8 +60,8 @@ namespace Remotely_ScreenCast { selectedScreen = 0; } - NeedsInit = true; } + NeedsInit = true; } } public bool NeedsInit { get; set; } @@ -86,8 +98,14 @@ namespace Remotely_ScreenCast output1 = output.QueryInterface(); // Width/Height of desktop to capture - width = output.Description.DesktopBounds.Right - output.Description.DesktopBounds.Left; - height = output.Description.DesktopBounds.Bottom - output.Description.DesktopBounds.Top; + var newWidth = output.Description.DesktopBounds.Right - output.Description.DesktopBounds.Left; + var newHeight = output.Description.DesktopBounds.Bottom - output.Description.DesktopBounds.Top; + if (newWidth != width || newHeight != height) + { + ScreenChanged(this, new Size(newWidth, newHeight)); + } + width = newWidth; + height = newHeight; CurrentFrame = new Bitmap(width, height); PreviousFrame = new Bitmap(width, height); @@ -128,7 +146,7 @@ namespace Remotely_ScreenCast var inputDesktop = Win32Interop.OpenInputDesktop(); var success = User32.SetThreadDesktop(inputDesktop); User32.CloseDesktop(inputDesktop); - Console.WriteLine($"Set thread desktop: {success}"); + Logger.Write($"Set thread desktop: {success}"); return; } @@ -185,16 +203,14 @@ namespace Remotely_ScreenCast { if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code) { - Trace.TraceError(e.Message); - Trace.TraceError(e.StackTrace); - Console.WriteLine($"Error: {e.Message}{Environment.NewLine}{e.StackTrace}"); + Logger.Write(e); Init(); Capture(); } } catch (Exception e) { - Console.WriteLine($"Error: {e.Message}{Environment.NewLine}{e.StackTrace}"); + Logger.Write(e); Init(); Capture(); } diff --git a/Remotely_ScreenCast/ICapturer.cs b/Remotely_ScreenCast/Capture/ICapturer.cs similarity index 54% rename from Remotely_ScreenCast/ICapturer.cs rename to Remotely_ScreenCast/Capture/ICapturer.cs index 7788fd08..0aeb661d 100644 --- a/Remotely_ScreenCast/ICapturer.cs +++ b/Remotely_ScreenCast/Capture/ICapturer.cs @@ -5,13 +5,17 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace Remotely_ScreenCast +namespace Remotely_ScreenCast.Capture { public interface ICapturer { Bitmap CurrentFrame { get; set; } - Bitmap PreviousFrame { get; set; } + Size CurrentScreenSize { get; } + + Bitmap PreviousFrame { get; set; } bool CaptureFullscreen { get; set; } void Capture(); - } + EventHandler ScreenChanged { get; set; } + int SelectedScreen { get; set; } + } } diff --git a/Remotely_ScreenCast/ImageDiff.cs b/Remotely_ScreenCast/Capture/ImageDiff.cs similarity index 99% rename from Remotely_ScreenCast/ImageDiff.cs rename to Remotely_ScreenCast/Capture/ImageDiff.cs index d9857bc9..7ce2985a 100644 --- a/Remotely_ScreenCast/ImageDiff.cs +++ b/Remotely_ScreenCast/Capture/ImageDiff.cs @@ -9,7 +9,7 @@ using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading.Tasks; -namespace Remotely_ScreenCast +namespace Remotely_ScreenCast.Capture { public class ImageDiff { diff --git a/Remotely_ScreenCast/Program.cs b/Remotely_ScreenCast/Program.cs index 1252eb7b..16695292 100644 --- a/Remotely_ScreenCast/Program.cs +++ b/Remotely_ScreenCast/Program.cs @@ -1,88 +1,98 @@ using Microsoft.AspNetCore.SignalR.Client; using Remotely_ScreenCapture; +using Remotely_ScreenCapture.Capture; +using Remotely_ScreenCapture.Sockets; +using Remotely_ScreenCapture.Utilities; +using Remotely_ScreenCast.Capture; using System; using System.Collections.Generic; using System.Diagnostics; +using System.Drawing; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; +using System.Windows.Forms; using Win32; namespace Remotely_ScreenCast { - class Program + public class Program { - static Stopwatch stopwatch; - static CaptureMode captureMode; + public static ICapturer Capturer { get; set; } + public static CaptureMode CaptureMode { get; set; } + public static bool DisconnectRequested { get; set; } + public static string Mode { get; set; } + public static string RequesterID { get; set; } + public static string HostName { get; set; } + public static HubConnection Connection { get; set; } + private static OutgoingMessages OutgoingMessages { get; set; } + static void Main(string[] args) { var argDict = ProcessArgs(args); - var mode = argDict["mode"]; - var requesterID = argDict["requester"]; - var hostname = argDict["hostname"]; + Mode = argDict["mode"]; + RequesterID = argDict["requester"]; + HostName = argDict["hostname"]; - var hubConnection = new HubConnectionBuilder() - .WithUrl($"https://{argDict["hostname"]}/DeviceHub") + Connection = new HubConnectionBuilder() + .WithUrl($"http://{HostName}/RCDeviceHub") .Build(); - hubConnection.Closed += (ex) => - { - Logger.Write($"Error: {ex.Message}"); - return Task.CompletedTask; - }; + MessageHandlers.ApplyConnectionHandlers(Connection); - hubConnection.StartAsync().Wait(); + Connection.StartAsync().Wait(); - var screenshotPath = $@"{Path.GetTempPath()}Screens\"; - if (!Directory.Exists(screenshotPath)) - { - Directory.CreateDirectory(screenshotPath); - } + OutgoingMessages = new OutgoingMessages(Connection); - - ICapturer capturer; try { - capturer = new DXCapture(); - captureMode = CaptureMode.DirectX; + Capturer = new DXCapture(); + CaptureMode = CaptureMode.DirectX; } catch { - capturer = new BitBltCapture(); - captureMode = CaptureMode.BitBtl; + Capturer = new BitBltCapture(); + CaptureMode = CaptureMode.BitBtl; } - while (true) + + OutgoingMessages.SendScreenCount( + Screen.AllScreens.ToList().IndexOf(Screen.PrimaryScreen), + Screen.AllScreens.Length, + RequesterID).Wait(); + + Capturer.ScreenChanged += HandleScreenChanged; + + OutgoingMessages.SendScreenSize(Capturer.CurrentScreenSize.Width, Capturer.CurrentScreenSize.Height).Wait(); + + while (!DisconnectRequested) { try { - capturer.Capture(); - var newImage = ImageDiff.GetImageDiff(capturer.CurrentFrame, capturer.PreviousFrame, capturer.CaptureFullscreen); + Capturer.Capture(); + var newImage = ImageDiff.GetImageDiff(Capturer.CurrentFrame, Capturer.PreviousFrame, Capturer.CaptureFullscreen); var img = ImageDiff.EncodeBitmap(newImage); - if (capturer.CaptureFullscreen) + if (Capturer.CaptureFullscreen) { - capturer.CaptureFullscreen = false; + Capturer.CaptureFullscreen = false; } if (img?.Length > 0) { - File.WriteAllBytes($@"{screenshotPath}{Path.GetRandomFileName()}.png", img); + OutgoingMessages.SendScreenCapture(img).Wait(); } } catch (Exception ex) { Logger.Write($"Outer Error: {ex.Message}{Environment.NewLine}{ex.StackTrace}"); } - System.Threading.Thread.Sleep(3000); } - } - enum CaptureMode + private static async void HandleScreenChanged(object sender, Size size) { - BitBtl, - DirectX + await OutgoingMessages.SendScreenSize(size.Width, size.Height); } private static Dictionary ProcessArgs(string[] args) @@ -105,5 +115,7 @@ namespace Remotely_ScreenCast } return argDict; } + + } } diff --git a/Remotely_ScreenCast/Remotely_ScreenCast.csproj b/Remotely_ScreenCast/Remotely_ScreenCast.csproj index 89a4717c..cd247d53 100644 --- a/Remotely_ScreenCast/Remotely_ScreenCast.csproj +++ b/Remotely_ScreenCast/Remotely_ScreenCast.csproj @@ -140,12 +140,15 @@ - - - - - - + + + + + + + + + @@ -162,6 +165,7 @@ + diff --git a/Remotely_ScreenCast/Sockets/MessageHandlers.cs b/Remotely_ScreenCast/Sockets/MessageHandlers.cs new file mode 100644 index 00000000..2cb8529e --- /dev/null +++ b/Remotely_ScreenCast/Sockets/MessageHandlers.cs @@ -0,0 +1,24 @@ +using Microsoft.AspNetCore.SignalR.Client; +using Remotely_ScreenCapture.Utilities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Remotely_ScreenCapture.Sockets +{ + public class MessageHandlers + { + public static void ApplyConnectionHandlers(HubConnection hubConnection) + { + hubConnection.Closed += (ex) => + { + Logger.Write($"Error: {ex.Message}"); + Environment.Exit(1); + return Task.CompletedTask; + }; + + } + } +} diff --git a/Remotely_ScreenCast/Sockets/OutgoingMessages.cs b/Remotely_ScreenCast/Sockets/OutgoingMessages.cs new file mode 100644 index 00000000..5dcf22b2 --- /dev/null +++ b/Remotely_ScreenCast/Sockets/OutgoingMessages.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore.SignalR.Client; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Remotely_ScreenCapture.Sockets +{ + public class OutgoingMessages + { + public OutgoingMessages(HubConnection hubConnection) + { + Connection = hubConnection; + } + + private HubConnection Connection { get; } + public async Task SendScreenSize(int width, int height) + { + await Connection.SendAsync("ScreenSize", width, height); + } + + public async Task SendScreenCapture(byte[] captureBytes) + { + await Connection.SendAsync("ScreenCapture", captureBytes); + } + + internal async Task SendScreenCount(int primaryScreenIndex, int screenCount, string requesterID) + { + await Connection.SendAsync("SendScreenCountToBrowser", primaryScreenIndex, screenCount, requesterID); + } + } +} diff --git a/Remotely_ScreenCast/Logger.cs b/Remotely_ScreenCast/Utilities/Logger.cs similarity index 98% rename from Remotely_ScreenCast/Logger.cs rename to Remotely_ScreenCast/Utilities/Logger.cs index 0d8ee1df..9687af17 100644 --- a/Remotely_ScreenCast/Logger.cs +++ b/Remotely_ScreenCast/Utilities/Logger.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace Remotely_ScreenCapture +namespace Remotely_ScreenCapture.Utilities { public static class Logger { diff --git a/Remotely_Server/Startup.cs b/Remotely_Server/Startup.cs index 129401e7..fe0611ec 100644 --- a/Remotely_Server/Startup.cs +++ b/Remotely_Server/Startup.cs @@ -116,6 +116,12 @@ namespace Remotely_Server app.UseCookiePolicy(); + // Uncomment to run .NET Core behind a reverse proxy. + //app.UseForwardedHeaders(new ForwardedHeadersOptions + //{ + // ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto + //}); + app.UseAuthentication(); app.UseSignalR(routes =>