mirror of
https://github.com/immense/Remotely.git
synced 2025-10-26 11:27:15 +00:00
Add IAppLauncher interface and create implementation per OS. Minor refactoring.
This commit is contained in:
parent
c9cbcd3b71
commit
378a318e2d
15
Agent/Interfaces/IAppLauncher.cs
Normal file
15
Agent/Interfaces/IAppLauncher.cs
Normal file
@ -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<int> LaunchChatService(string orgName, string requesterID, HubConnection hubConnection);
|
||||
Task LaunchRemoteControl(int targetSessionId, string requesterID, string serviceID, HubConnection hubConnection);
|
||||
Task RestartScreenCaster(List<string> viewerIDs, string serviceID, string requesterID, HubConnection hubConnection, int targetSessionID = -1);
|
||||
}
|
||||
}
|
||||
@ -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<Uninstaller>();
|
||||
serviceCollection.AddScoped<ScriptRunner>();
|
||||
serviceCollection.AddScoped<CommandExecutor>();
|
||||
serviceCollection.AddScoped<AppLauncher>();
|
||||
|
||||
if (EnvironmentHelper.IsWindows)
|
||||
{
|
||||
serviceCollection.AddScoped<IAppLauncher, AppLauncherWin>();
|
||||
}
|
||||
else if (EnvironmentHelper.IsLinux)
|
||||
{
|
||||
serviceCollection.AddScoped<IAppLauncher, AppLauncherLinux>();
|
||||
}
|
||||
else if (EnvironmentHelper.IsMac)
|
||||
{
|
||||
// TODO: Mac.
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotSupportedException("Operating system not supported.");
|
||||
}
|
||||
|
||||
Services = serviceCollection.BuildServiceProvider();
|
||||
}
|
||||
|
||||
@ -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; }
|
||||
|
||||
@ -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<int> 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<string> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
138
Agent/Services/AppLauncherLinux.cs
Normal file
138
Agent/Services/AppLauncherLinux.cs
Normal file
@ -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<int> 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<string> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
150
Agent/Services/AppLauncherWin.cs
Normal file
150
Agent/Services/AppLauncherWin.cs
Normal file
@ -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<int> 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<string> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
});
|
||||
|
||||
@ -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<ClipboardTransferDto>(message);
|
||||
if (dto.TypeText)
|
||||
@ -154,7 +154,7 @@ namespace Remotely.Desktop.Core.Services
|
||||
}
|
||||
else
|
||||
{
|
||||
ClipboardService.SetText(dto.Text);
|
||||
await ClipboardService.SetText(dto.Text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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<IChatHostService>().StartChat(Conductor.RequesterID, Conductor.OrganizationName).Wait();
|
||||
await Services.GetRequiredService<IChatHostService>().StartChat(Conductor.RequesterID, Conductor.OrganizationName);
|
||||
}
|
||||
else if (Conductor.Mode == Core.Enums.AppMode.Unattended)
|
||||
{
|
||||
var casterSocket = Services.GetRequiredService<CasterSocket>();
|
||||
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);
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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<IChatHostService>();
|
||||
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
|
||||
{
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user