diff --git a/Agent/Interfaces/IAppLauncher.cs b/Agent/Interfaces/IAppLauncher.cs new file mode 100644 index 00000000..d8ac03b0 --- /dev/null +++ b/Agent/Interfaces/IAppLauncher.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.SignalR.Client; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace Remotely.Agent.Interfaces +{ + public interface IAppLauncher + { + Task LaunchChatService(string orgName, string requesterID, HubConnection hubConnection); + Task LaunchRemoteControl(int targetSessionId, string requesterID, string serviceID, HubConnection hubConnection); + Task RestartScreenCaster(List viewerIDs, string serviceID, string requesterID, HubConnection hubConnection, int targetSessionID = -1); + } +} diff --git a/Agent/Program.cs b/Agent/Program.cs index f9041d7e..4da8c3de 100644 --- a/Agent/Program.cs +++ b/Agent/Program.cs @@ -7,6 +7,7 @@ using System.Threading; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Remotely.Shared.Utilities; +using Remotely.Agent.Interfaces; namespace Remotely.Agent { @@ -29,6 +30,7 @@ namespace Remotely.Agent catch (Exception ex) { Logger.Write(ex); + throw; } } @@ -50,7 +52,23 @@ namespace Remotely.Agent serviceCollection.AddScoped(); serviceCollection.AddScoped(); serviceCollection.AddScoped(); - serviceCollection.AddScoped(); + + if (EnvironmentHelper.IsWindows) + { + serviceCollection.AddScoped(); + } + else if (EnvironmentHelper.IsLinux) + { + serviceCollection.AddScoped(); + } + else if (EnvironmentHelper.IsMac) + { + // TODO: Mac. + } + else + { + throw new NotSupportedException("Operating system not supported."); + } Services = serviceCollection.BuildServiceProvider(); } diff --git a/Agent/Services/AgentSocket.cs b/Agent/Services/AgentSocket.cs index cc3315b7..fa8b6159 100644 --- a/Agent/Services/AgentSocket.cs +++ b/Agent/Services/AgentSocket.cs @@ -15,6 +15,7 @@ using System.Text.Json; using System.Threading; using Remotely.Shared.Utilities; using Remotely.Shared.Enums; +using Remotely.Agent.Interfaces; namespace Remotely.Agent.Services { @@ -24,7 +25,7 @@ namespace Remotely.Agent.Services Uninstaller uninstaller, CommandExecutor commandExecutor, ScriptRunner scriptRunner, - AppLauncher appLauncher, + IAppLauncher appLauncher, ChatClientService chatService) { ConfigService = configService; @@ -35,7 +36,7 @@ namespace Remotely.Agent.Services ChatService = chatService; } public bool IsConnected => HubConnection?.State == HubConnectionState.Connected; - private AppLauncher AppLauncher { get; } + private IAppLauncher AppLauncher { get; } private ChatClientService ChatService { get; } private CommandExecutor CommandExecutor { get; } private ConfigService ConfigService { get; } diff --git a/Agent/Services/AppLauncher.cs b/Agent/Services/AppLauncher.cs deleted file mode 100644 index 067d313c..00000000 --- a/Agent/Services/AppLauncher.cs +++ /dev/null @@ -1,223 +0,0 @@ -using Microsoft.AspNetCore.SignalR.Client; -using Remotely.Shared.Models; -using Remotely.Shared.Utilities; -using Remotely.Shared.Win32; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -namespace Remotely.Agent.Services -{ - public class AppLauncher - { - public AppLauncher(ConfigService configService) - { - ConnectionInfo = configService.GetConnectionInfo(); - } - - private ConnectionInfo ConnectionInfo { get; } - - public async Task LaunchChatService(string orgName, string requesterID, HubConnection hubConnection) - { - try - { - var rcBinaryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Desktop", EnvironmentHelper.DesktopExecutableFileName); - if (!File.Exists(rcBinaryPath)) - { - await hubConnection.SendAsync("DisplayMessage", "Chat executable not found on target device.", "Executable not found on device.", requesterID); - } - - - // Start Desktop app. - await hubConnection.SendAsync("DisplayMessage", $"Starting chat service...", "Starting chat service.", requesterID); - if (EnvironmentHelper.IsWindows) - { - - if (EnvironmentHelper.IsDebug) - { - return Process.Start(rcBinaryPath, $"-mode Chat -requester \"{requesterID}\" -organization \"{orgName}\"").Id; - } - else - { - var result = Win32Interop.OpenInteractiveProcess($"{rcBinaryPath} -mode Chat -requester \"{requesterID}\" -organization \"{orgName}\"", - targetSessionId: -1, - forceConsoleSession: false, - desktopName: "default", - hiddenWindow: false, - out var procInfo); - if (!result) - { - await hubConnection.SendAsync("DisplayMessage", "Chat service failed to start on target device.", "Failed to start chat service.", requesterID); - } - else - { - return procInfo.dwProcessId; - } - } - } - else if (EnvironmentHelper.IsLinux) - { - var args = $"{rcBinaryPath} -mode Chat -requester \"{requesterID}\" -organization \"{orgName}\" & disown"; - return StartLinuxDesktopApp(args); - } - } - catch (Exception ex) - { - Logger.Write(ex); - await hubConnection.SendAsync("DisplayMessage", "Chat service failed to start on target device.", "Failed to start chat service.", requesterID); - } - return -1; - } - - public async Task LaunchRemoteControl(int targetSessionId, string requesterID, string serviceID, HubConnection hubConnection) - { - try - { - var rcBinaryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Desktop", EnvironmentHelper.DesktopExecutableFileName); - if (!File.Exists(rcBinaryPath)) - { - await hubConnection.SendAsync("DisplayMessage", "Remote control executable not found on target device.", "Executable not found on device.", requesterID); - return; - } - - - // Start Desktop app. - await hubConnection.SendAsync("DisplayMessage", $"Starting remote control...", "Starting remote control.", requesterID); - if (EnvironmentHelper.IsWindows) - { - - if (EnvironmentHelper.IsDebug) - { - // SignalR Connection IDs might start with a hyphen. We surround them - // with quotes so the command line will be parsed correctly. - Process.Start(rcBinaryPath, $"-mode Unattended -requester \"{requesterID}\" -serviceid \"{serviceID}\" -deviceid {ConnectionInfo.DeviceID} -host {ConnectionInfo.Host}"); - } - else - { - var result = Win32Interop.OpenInteractiveProcess(rcBinaryPath + $" -mode Unattended -requester \"{requesterID}\" -serviceid \"{serviceID}\" -deviceid {ConnectionInfo.DeviceID} -host {ConnectionInfo.Host}", - targetSessionId: targetSessionId, - forceConsoleSession: false, - desktopName: "default", - hiddenWindow: true, - out _); - if (!result) - { - await hubConnection.SendAsync("DisplayMessage", "Remote control failed to start on target device.", "Failed to start remote control.", requesterID); - } - } - } - else if (EnvironmentHelper.IsLinux) - { - var args = $"{rcBinaryPath} -mode Unattended -requester \"{requesterID}\" -serviceid \"{serviceID}\" -deviceid {ConnectionInfo.DeviceID} -host {ConnectionInfo.Host} & disown"; - StartLinuxDesktopApp(args); - } - } - catch (Exception ex) - { - Logger.Write(ex); - await hubConnection.SendAsync("DisplayMessage", "Remote control failed to start on target device.", "Failed to start remote control.", requesterID); - } - } - public async Task RestartScreenCaster(List viewerIDs, string serviceID, string requesterID, HubConnection hubConnection, int targetSessionID = -1) - { - try - { - var rcBinaryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Desktop", EnvironmentHelper.DesktopExecutableFileName); - // Start Desktop app. - if (EnvironmentHelper.IsWindows) - { - Logger.Write("Restarting screen caster."); - if (EnvironmentHelper.IsDebug) - { - // SignalR Connection IDs might start with a hyphen. We surround them - // with quotes so the command line will be parsed correctly. - Process.Start(rcBinaryPath, $"-mode Unattended -requester \"{requesterID}\" -serviceid \"{serviceID}\" -deviceid {ConnectionInfo.DeviceID} -host {ConnectionInfo.Host} -relaunch true -viewers {String.Join(",", viewerIDs)}"); - } - else - { - - // Give a little time for session changing, etc. - await Task.Delay(1000); - - var result = Win32Interop.OpenInteractiveProcess(rcBinaryPath + $" -mode Unattended -requester \"{requesterID}\" -serviceid \"{serviceID}\" -deviceid {ConnectionInfo.DeviceID} -host {ConnectionInfo.Host} -relaunch true -viewers {String.Join(",", viewerIDs)}", - targetSessionId: targetSessionID, - forceConsoleSession: Shlwapi.IsOS(OsType.OS_ANYSERVER) && targetSessionID == -1 ? true : false, - desktopName: "default", - hiddenWindow: true, - out _); - - if (!result) - { - Logger.Write("Failed to relaunch screen caster."); - await hubConnection.SendAsync("SendConnectionFailedToViewers", viewerIDs); - await hubConnection.SendAsync("DisplayMessage", "Remote control failed to start on target device.", "Failed to start remote control.", requesterID); - } - } - } - else if (EnvironmentHelper.IsLinux) - { - var args = $"{rcBinaryPath} -mode Unattended -requester \"{requesterID}\" -serviceid \"{serviceID}\" -deviceid {ConnectionInfo.DeviceID} -host {ConnectionInfo.Host} -relaunch true -viewers {string.Join(",", viewerIDs)} & disown"; - StartLinuxDesktopApp(args); - } - } - catch (Exception ex) - { - await hubConnection.SendAsync("SendConnectionFailedToViewers", viewerIDs); - Logger.Write(ex); - throw; - } - } - - private int StartLinuxDesktopApp(string args) - { - var xauthority = string.Empty; - - var processes = EnvironmentHelper.StartProcessWithResults("ps", "-eaf").Split(Environment.NewLine); - var xorgLine = processes.FirstOrDefault(x => x.Contains("xorg")); - var xorgSplit = xorgLine.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList(); - var auth = xorgSplit[xorgSplit.IndexOf("-auth") + 1]; - if (!string.IsNullOrWhiteSpace(auth)) - { - xauthority = auth; - } - - var display = ":0"; - var whoString = EnvironmentHelper.StartProcessWithResults("w", "-h")?.Trim(); - var username = string.Empty; - - if (!string.IsNullOrWhiteSpace(whoString)) - { - try - { - var whoLine = whoString - .Split('\n', StringSplitOptions.RemoveEmptyEntries) - .First(); - - var whoSplit = whoLine.Split(' ', StringSplitOptions.RemoveEmptyEntries); - username = whoSplit[0]; - display = whoSplit[2]; - xauthority = $"/home/{username}/.Xauthority"; - args = $"-u {username} {args}"; - } - catch (Exception ex) - { - Logger.Write(ex); - } - } - - var psi = new ProcessStartInfo() - { - FileName = "sudo", - Arguments = args - }; - - psi.Environment.Add("DISPLAY", display); - psi.Environment.Add("XAUTHORITY", xauthority); - Logger.Write($"Attempting to launch screen caster with username {username}, xauthority {xauthority}, display {display}, and args {args}."); - return Process.Start(psi).Id; - } - } -} diff --git a/Agent/Services/AppLauncherLinux.cs b/Agent/Services/AppLauncherLinux.cs new file mode 100644 index 00000000..34e6d29b --- /dev/null +++ b/Agent/Services/AppLauncherLinux.cs @@ -0,0 +1,138 @@ +using Microsoft.AspNetCore.SignalR.Client; +using Remotely.Agent.Interfaces; +using Remotely.Shared.Models; +using Remotely.Shared.Utilities; +using Remotely.Shared.Win32; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace Remotely.Agent.Services +{ + + public class AppLauncherLinux : IAppLauncher + { + public AppLauncherLinux(ConfigService configService) + { + ConnectionInfo = configService.GetConnectionInfo(); + } + + private ConnectionInfo ConnectionInfo { get; } + + public async Task LaunchChatService(string orgName, string requesterID, HubConnection hubConnection) + { + try + { + var rcBinaryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Desktop", EnvironmentHelper.DesktopExecutableFileName); + if (!File.Exists(rcBinaryPath)) + { + await hubConnection.SendAsync("DisplayMessage", "Chat executable not found on target device.", "Executable not found on device.", requesterID); + } + + + // Start Desktop app. + await hubConnection.SendAsync("DisplayMessage", $"Starting chat service...", "Starting chat service.", requesterID); + var args = $"{rcBinaryPath} -mode Chat -requester \"{requesterID}\" -organization \"{orgName}\" & disown"; + return StartLinuxDesktopApp(args); + } + catch (Exception ex) + { + Logger.Write(ex); + await hubConnection.SendAsync("DisplayMessage", "Chat service failed to start on target device.", "Failed to start chat service.", requesterID); + } + return -1; + } + + public async Task LaunchRemoteControl(int targetSessionId, string requesterID, string serviceID, HubConnection hubConnection) + { + try + { + var rcBinaryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Desktop", EnvironmentHelper.DesktopExecutableFileName); + if (!File.Exists(rcBinaryPath)) + { + await hubConnection.SendAsync("DisplayMessage", "Remote control executable not found on target device.", "Executable not found on device.", requesterID); + return; + } + + + // Start Desktop app. + await hubConnection.SendAsync("DisplayMessage", $"Starting remote control...", "Starting remote control.", requesterID); + var args = $"{rcBinaryPath} -mode Unattended -requester \"{requesterID}\" -serviceid \"{serviceID}\" -deviceid {ConnectionInfo.DeviceID} -host {ConnectionInfo.Host} & disown"; + StartLinuxDesktopApp(args); + } + catch (Exception ex) + { + Logger.Write(ex); + await hubConnection.SendAsync("DisplayMessage", "Remote control failed to start on target device.", "Failed to start remote control.", requesterID); + } + } + public async Task RestartScreenCaster(List viewerIDs, string serviceID, string requesterID, HubConnection hubConnection, int targetSessionID = -1) + { + try + { + var rcBinaryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Desktop", EnvironmentHelper.DesktopExecutableFileName); + // Start Desktop app. + var args = $"{rcBinaryPath} -mode Unattended -requester \"{requesterID}\" -serviceid \"{serviceID}\" -deviceid {ConnectionInfo.DeviceID} -host {ConnectionInfo.Host} -relaunch true -viewers {string.Join(",", viewerIDs)} & disown"; + StartLinuxDesktopApp(args); + } + catch (Exception ex) + { + await hubConnection.SendAsync("SendConnectionFailedToViewers", viewerIDs); + Logger.Write(ex); + throw; + } + } + + private int StartLinuxDesktopApp(string args) + { + var xauthority = string.Empty; + + var processes = EnvironmentHelper.StartProcessWithResults("ps", "-eaf").Split(Environment.NewLine); + var xorgLine = processes.FirstOrDefault(x => x.Contains("xorg")); + var xorgSplit = xorgLine.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList(); + var auth = xorgSplit[xorgSplit.IndexOf("-auth") + 1]; + if (!string.IsNullOrWhiteSpace(auth)) + { + xauthority = auth; + } + + var display = ":0"; + var whoString = EnvironmentHelper.StartProcessWithResults("w", "-h")?.Trim(); + var username = string.Empty; + + if (!string.IsNullOrWhiteSpace(whoString)) + { + try + { + var whoLine = whoString + .Split('\n', StringSplitOptions.RemoveEmptyEntries) + .First(); + + var whoSplit = whoLine.Split(' ', StringSplitOptions.RemoveEmptyEntries); + username = whoSplit[0]; + display = whoSplit[2]; + xauthority = $"/home/{username}/.Xauthority"; + args = $"-u {username} {args}"; + } + catch (Exception ex) + { + Logger.Write(ex); + } + } + + var psi = new ProcessStartInfo() + { + FileName = "sudo", + Arguments = args + }; + + psi.Environment.Add("DISPLAY", display); + psi.Environment.Add("XAUTHORITY", xauthority); + Logger.Write($"Attempting to launch screen caster with username {username}, xauthority {xauthority}, display {display}, and args {args}."); + return Process.Start(psi).Id; + } + } +} diff --git a/Agent/Services/AppLauncherWin.cs b/Agent/Services/AppLauncherWin.cs new file mode 100644 index 00000000..9f338a0f --- /dev/null +++ b/Agent/Services/AppLauncherWin.cs @@ -0,0 +1,150 @@ +using Microsoft.AspNetCore.SignalR.Client; +using Remotely.Agent.Interfaces; +using Remotely.Shared.Models; +using Remotely.Shared.Utilities; +using Remotely.Shared.Win32; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace Remotely.Agent.Services +{ + + public class AppLauncherWin : IAppLauncher + { + public AppLauncherWin(ConfigService configService) + { + ConnectionInfo = configService.GetConnectionInfo(); + } + + private ConnectionInfo ConnectionInfo { get; } + + public async Task LaunchChatService(string orgName, string requesterID, HubConnection hubConnection) + { + try + { + var rcBinaryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Desktop", EnvironmentHelper.DesktopExecutableFileName); + if (!File.Exists(rcBinaryPath)) + { + await hubConnection.SendAsync("DisplayMessage", "Chat executable not found on target device.", "Executable not found on device.", requesterID); + } + + + // Start Desktop app. + await hubConnection.SendAsync("DisplayMessage", $"Starting chat service...", "Starting chat service.", requesterID); + if (EnvironmentHelper.IsDebug) + { + return Process.Start(rcBinaryPath, $"-mode Chat -requester \"{requesterID}\" -organization \"{orgName}\"").Id; + } + else + { + var result = Win32Interop.OpenInteractiveProcess($"{rcBinaryPath} -mode Chat -requester \"{requesterID}\" -organization \"{orgName}\"", + targetSessionId: -1, + forceConsoleSession: false, + desktopName: "default", + hiddenWindow: false, + out var procInfo); + if (!result) + { + await hubConnection.SendAsync("DisplayMessage", "Chat service failed to start on target device.", "Failed to start chat service.", requesterID); + } + else + { + return procInfo.dwProcessId; + } + } + } + catch (Exception ex) + { + Logger.Write(ex); + await hubConnection.SendAsync("DisplayMessage", "Chat service failed to start on target device.", "Failed to start chat service.", requesterID); + } + return -1; + } + + public async Task LaunchRemoteControl(int targetSessionId, string requesterID, string serviceID, HubConnection hubConnection) + { + try + { + var rcBinaryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Desktop", EnvironmentHelper.DesktopExecutableFileName); + if (!File.Exists(rcBinaryPath)) + { + await hubConnection.SendAsync("DisplayMessage", "Remote control executable not found on target device.", "Executable not found on device.", requesterID); + return; + } + + + // Start Desktop app. + await hubConnection.SendAsync("DisplayMessage", $"Starting remote control...", "Starting remote control.", requesterID); + if (EnvironmentHelper.IsDebug) + { + // SignalR Connection IDs might start with a hyphen. We surround them + // with quotes so the command line will be parsed correctly. + Process.Start(rcBinaryPath, $"-mode Unattended -requester \"{requesterID}\" -serviceid \"{serviceID}\" -deviceid {ConnectionInfo.DeviceID} -host {ConnectionInfo.Host}"); + } + else + { + var result = Win32Interop.OpenInteractiveProcess(rcBinaryPath + $" -mode Unattended -requester \"{requesterID}\" -serviceid \"{serviceID}\" -deviceid {ConnectionInfo.DeviceID} -host {ConnectionInfo.Host}", + targetSessionId: targetSessionId, + forceConsoleSession: false, + desktopName: "default", + hiddenWindow: true, + out _); + if (!result) + { + await hubConnection.SendAsync("DisplayMessage", "Remote control failed to start on target device.", "Failed to start remote control.", requesterID); + } + } + } + catch (Exception ex) + { + Logger.Write(ex); + await hubConnection.SendAsync("DisplayMessage", "Remote control failed to start on target device.", "Failed to start remote control.", requesterID); + } + } + public async Task RestartScreenCaster(List viewerIDs, string serviceID, string requesterID, HubConnection hubConnection, int targetSessionID = -1) + { + try + { + var rcBinaryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Desktop", EnvironmentHelper.DesktopExecutableFileName); + // Start Desktop app. + Logger.Write("Restarting screen caster."); + if (EnvironmentHelper.IsDebug) + { + // SignalR Connection IDs might start with a hyphen. We surround them + // with quotes so the command line will be parsed correctly. + Process.Start(rcBinaryPath, $"-mode Unattended -requester \"{requesterID}\" -serviceid \"{serviceID}\" -deviceid {ConnectionInfo.DeviceID} -host {ConnectionInfo.Host} -relaunch true -viewers {String.Join(",", viewerIDs)}"); + } + else + { + + // Give a little time for session changing, etc. + await Task.Delay(1000); + + var result = Win32Interop.OpenInteractiveProcess(rcBinaryPath + $" -mode Unattended -requester \"{requesterID}\" -serviceid \"{serviceID}\" -deviceid {ConnectionInfo.DeviceID} -host {ConnectionInfo.Host} -relaunch true -viewers {String.Join(",", viewerIDs)}", + targetSessionId: targetSessionID, + forceConsoleSession: Shlwapi.IsOS(OsType.OS_ANYSERVER) && targetSessionID == -1, + desktopName: "default", + hiddenWindow: true, + out _); + + if (!result) + { + Logger.Write("Failed to relaunch screen caster."); + await hubConnection.SendAsync("SendConnectionFailedToViewers", viewerIDs); + await hubConnection.SendAsync("DisplayMessage", "Remote control failed to start on target device.", "Failed to start remote control.", requesterID); + } + } + } + catch (Exception ex) + { + await hubConnection.SendAsync("SendConnectionFailedToViewers", viewerIDs); + Logger.Write(ex); + throw; + } + } + } +} diff --git a/Agent/Services/ChatClientService.cs b/Agent/Services/ChatClientService.cs index 5400f0d6..a9256eed 100644 --- a/Agent/Services/ChatClientService.cs +++ b/Agent/Services/ChatClientService.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.SignalR.Client; +using Remotely.Agent.Interfaces; using Remotely.Agent.Models; using Remotely.Shared.Models; using Remotely.Shared.Utilities; @@ -15,13 +16,13 @@ namespace Remotely.Agent.Services { public class ChatClientService { - public ChatClientService(AppLauncher appLauncher) + public ChatClientService(IAppLauncher appLauncher) { AppLauncher = appLauncher; } private SemaphoreSlim MessageLock { get; } = new SemaphoreSlim(1); - private AppLauncher AppLauncher { get; } + private IAppLauncher AppLauncher { get; } private CacheItemPolicy CacheItemPolicy { get; } = new CacheItemPolicy() { SlidingExpiration = TimeSpan.FromMinutes(10), @@ -34,6 +35,7 @@ namespace Remotely.Agent.Services }; private MemoryCache ChatClients { get; } = new MemoryCache("ChatClients"); + public async Task SendMessage(string senderName, string message, string orgName, diff --git a/Desktop.Core/Interfaces/IClipboardService.cs b/Desktop.Core/Interfaces/IClipboardService.cs index df045d62..13dd6d0d 100644 --- a/Desktop.Core/Interfaces/IClipboardService.cs +++ b/Desktop.Core/Interfaces/IClipboardService.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; namespace Remotely.Desktop.Core.Interfaces { @@ -8,6 +9,6 @@ namespace Remotely.Desktop.Core.Interfaces void BeginWatching(); - void SetText(string clipboardText); + Task SetText(string clipboardText); } } diff --git a/Desktop.Core/Services/CasterSocket.cs b/Desktop.Core/Services/CasterSocket.cs index 0d875767..2828bd54 100644 --- a/Desktop.Core/Services/CasterSocket.cs +++ b/Desktop.Core/Services/CasterSocket.cs @@ -236,7 +236,7 @@ namespace Remotely.Desktop.Core.Services } }); - Connection.On("ClipboardTransfer", (string transferText, bool typeText, string viewerID) => + Connection.On("ClipboardTransfer", async (string transferText, bool typeText, string viewerID) => { try { @@ -248,7 +248,7 @@ namespace Remotely.Desktop.Core.Services } else { - ClipboardService.SetText(transferText); + await ClipboardService.SetText(transferText); } } } @@ -523,12 +523,11 @@ namespace Remotely.Desktop.Core.Services var dirPath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "RemotelySharedFiles")).FullName; var filePath = Path.Combine(dirPath, fileName); + using (var fs = new FileStream(filePath, FileMode.Create)) + using (var rs = response.GetResponseStream()) { - using (var rs = response.GetResponseStream()) - { - rs.CopyTo(fs); - } + rs.CopyTo(fs); } Process.Start("explorer.exe", dirPath); }); diff --git a/Desktop.Core/Services/RtcMessageHandler.cs b/Desktop.Core/Services/RtcMessageHandler.cs index ae83139c..1f978b1a 100644 --- a/Desktop.Core/Services/RtcMessageHandler.cs +++ b/Desktop.Core/Services/RtcMessageHandler.cs @@ -115,7 +115,7 @@ namespace Remotely.Desktop.Core.Services ToggleWebRtcVideo(message); break; case BinaryDtoType.ClipboardTransfer: - ClipboardTransfer(message); + await ClipboardTransfer(message); break; case BinaryDtoType.KeyPress: await KeyPress(message); @@ -145,7 +145,7 @@ namespace Remotely.Desktop.Core.Services } } - private void ClipboardTransfer(byte[] message) + private async Task ClipboardTransfer(byte[] message) { var dto = MessagePackSerializer.Deserialize(message); if (dto.TypeText) @@ -154,7 +154,7 @@ namespace Remotely.Desktop.Core.Services } else { - ClipboardService.SetText(dto.Text); + await ClipboardService.SetText(dto.Text); } } diff --git a/Desktop.Linux/Program.cs b/Desktop.Linux/Program.cs index b326af32..2e4a8073 100644 --- a/Desktop.Linux/Program.cs +++ b/Desktop.Linux/Program.cs @@ -32,7 +32,7 @@ namespace Remotely.Desktop.Linux public static Conductor Conductor { get; private set; } public static IServiceProvider Services => ServiceContainer.Instance; - public static void Main(string[] args) + public static async Task Main(string[] args) { try { @@ -45,7 +45,7 @@ namespace Remotely.Desktop.Linux Logger.Write("Processing Args: " + string.Join(", ", Environment.GetCommandLineArgs())); Conductor.ProcessArgs(args); - Task.Run(() => + _ = Task.Run(() => { BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); }); @@ -57,12 +57,12 @@ namespace Remotely.Desktop.Linux if (Conductor.Mode == Core.Enums.AppMode.Chat) { - Services.GetRequiredService().StartChat(Conductor.RequesterID, Conductor.OrganizationName).Wait(); + await Services.GetRequiredService().StartChat(Conductor.RequesterID, Conductor.OrganizationName); } else if (Conductor.Mode == Core.Enums.AppMode.Unattended) { var casterSocket = Services.GetRequiredService(); - casterSocket.Connect(Conductor.Host).ContinueWith(async (task) => + await casterSocket.Connect(Conductor.Host).ContinueWith(async (task) => { await casterSocket.SendDeviceInfo(Conductor.ServiceID, Environment.MachineName, Conductor.DeviceID); await casterSocket.NotifyRequesterUnattendedReady(Conductor.RequesterID); diff --git a/Desktop.Linux/Services/ClipboardServiceLinux.cs b/Desktop.Linux/Services/ClipboardServiceLinux.cs index 9104f226..03a204eb 100644 --- a/Desktop.Linux/Services/ClipboardServiceLinux.cs +++ b/Desktop.Linux/Services/ClipboardServiceLinux.cs @@ -30,17 +30,17 @@ namespace Remotely.Desktop.Linux.Services } } - public void SetText(string clipboardText) + public async Task SetText(string clipboardText) { try { if (string.IsNullOrWhiteSpace(clipboardText)) { - App.Current.Clipboard.ClearAsync().Wait(); + await App.Current.Clipboard.ClearAsync(); } else { - App.Current.Clipboard.SetTextAsync(clipboardText).Wait(); + await App.Current.Clipboard.SetTextAsync(clipboardText); } } catch (Exception ex) diff --git a/Desktop.Win/Program.cs b/Desktop.Win/Program.cs index 777d7ce2..93443888 100644 --- a/Desktop.Win/Program.cs +++ b/Desktop.Win/Program.cs @@ -36,7 +36,7 @@ namespace Remotely.Desktop.Win } } [STAThread] - public static void Main(string[] args) + public static async Task Main(string[] args) { try { @@ -51,7 +51,7 @@ namespace Remotely.Desktop.Win if (Conductor.Mode == Core.Enums.AppMode.Chat) { StartUiThread(null); - _ = Task.Run(async () => + await Task.Run(async () => { var chatService = Services.GetRequiredService(); await chatService.StartChat(Conductor.RequesterID, Conductor.OrganizationName); @@ -64,7 +64,7 @@ namespace Remotely.Desktop.Win { App.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown; }); - _ = Task.Run(StartScreenCasting); + await Task.Run(StartScreenCasting); } else { diff --git a/Desktop.Win/Services/ClipboardServiceWin.cs b/Desktop.Win/Services/ClipboardServiceWin.cs index 26c39521..47625461 100644 --- a/Desktop.Win/Services/ClipboardServiceWin.cs +++ b/Desktop.Win/Services/ClipboardServiceWin.cs @@ -31,7 +31,7 @@ namespace Remotely.Desktop.Win.Services } } - public void SetText(string clipboardText) + public Task SetText(string clipboardText) { var thread = new Thread(() => { @@ -53,7 +53,8 @@ namespace Remotely.Desktop.Win.Services }); thread.SetApartmentState(ApartmentState.STA); thread.Start(); - + + return Task.CompletedTask; } public void StopWatching() diff --git a/Shared/Utilities/EnvironmentHelper.cs b/Shared/Utilities/EnvironmentHelper.cs index 4fe38225..921ef4a0 100644 --- a/Shared/Utilities/EnvironmentHelper.cs +++ b/Shared/Utilities/EnvironmentHelper.cs @@ -24,6 +24,25 @@ namespace Remotely.Shared.Utilities } } + public static string DesktopExecutableFileName + { + get + { + if (IsWindows) + { + return "Remotely_Desktop.exe"; + } + else if (IsLinux) + { + return "Remotely_Desktop"; + } + else + { + throw new Exception("Unsupported operating system."); + } + } + } + public static bool IsDebug { get @@ -35,21 +54,12 @@ namespace Remotely.Shared.Utilities #endif } } - public static bool IsLinux - { - get - { - return RuntimeInformation.IsOSPlatform(OSPlatform.Linux); - } - } + public static bool IsLinux => RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + + public static bool IsMac => RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + + public static bool IsWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - public static bool IsWindows - { - get - { - return RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - } - } public static Platform Platform { get @@ -72,37 +82,17 @@ namespace Remotely.Shared.Utilities } } } - - public static string DesktopExecutableFileName - { - get - { - if (IsWindows) - { - return "Remotely_Desktop.exe"; - } - else if (IsLinux) - { - return "Remotely_Desktop"; - } - else - { - throw new Exception("Unsupported operating system."); - } - } - } public static string StartProcessWithResults(string command, string arguments) { - var psi = new ProcessStartInfo(command, arguments); - psi.WindowStyle = ProcessWindowStyle.Hidden; - psi.Verb = "RunAs"; - psi.UseShellExecute = false; - psi.RedirectStandardOutput = true; + var psi = new ProcessStartInfo(command, arguments) + { + WindowStyle = ProcessWindowStyle.Hidden, + Verb = "RunAs", + UseShellExecute = false, + RedirectStandardOutput = true + }; - var proc = new Process(); - proc.StartInfo = psi; - - proc.Start(); + var proc = Process.Start(psi); proc.WaitForExit(); return proc.StandardOutput.ReadToEnd();