From 30dbfb5ac9f1e35981f757ce761377438d84bd4c Mon Sep 17 00:00:00 2001 From: Jared Goodwin Date: Sat, 23 Feb 2019 15:23:39 -0800 Subject: [PATCH] Rebranding. --- .../Resources/Remotely_ScreenCapture.exe | Bin 1171968 -> 1180672 bytes Remotely_Agent/Services/ClientSocket.cs | 11 +-- Remotely_Library/Models/ConnectionInfo.cs | 2 - .../{ => Capture}/BitBltCapture.cs | 22 ++++- Remotely_ScreenCast/Capture/CaptureMode.cs | 14 +++ .../{ => Capture}/CursorIconWatcher.cs | 2 +- .../{ => Capture}/DXCapture.cs | 38 +++++--- .../{ => Capture}/ICapturer.cs | 10 ++- .../{ => Capture}/ImageDiff.cs | 2 +- Remotely_ScreenCast/Program.cs | 84 ++++++++++-------- .../Remotely_ScreenCast.csproj | 16 ++-- .../Sockets/MessageHandlers.cs | 24 +++++ .../Sockets/OutgoingMessages.cs | 33 +++++++ Remotely_ScreenCast/{ => Utilities}/Logger.cs | 2 +- Remotely_Server/Startup.cs | 6 ++ 15 files changed, 193 insertions(+), 73 deletions(-) rename Remotely_ScreenCast/{ => Capture}/BitBltCapture.cs (85%) create mode 100644 Remotely_ScreenCast/Capture/CaptureMode.cs rename Remotely_ScreenCast/{ => Capture}/CursorIconWatcher.cs (97%) rename Remotely_ScreenCast/{ => Capture}/DXCapture.cs (85%) rename Remotely_ScreenCast/{ => Capture}/ICapturer.cs (54%) rename Remotely_ScreenCast/{ => Capture}/ImageDiff.cs (99%) create mode 100644 Remotely_ScreenCast/Sockets/MessageHandlers.cs create mode 100644 Remotely_ScreenCast/Sockets/OutgoingMessages.cs rename Remotely_ScreenCast/{ => Utilities}/Logger.cs (98%) diff --git a/Remotely_Agent/Resources/Remotely_ScreenCapture.exe b/Remotely_Agent/Resources/Remotely_ScreenCapture.exe index 3f7f219616927d1cf095334ce0ecf6a4e5aa36d0..9e29f50e57a8a24b4480cabffceb32d1870b0b36 100644 GIT binary patch delta 40806 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 delta 31992 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 { - 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 =>