diff --git a/Agent/Agent.csproj b/Agent/Agent.csproj index 13a3e745..d8162dc4 100644 --- a/Agent/Agent.csproj +++ b/Agent/Agent.csproj @@ -25,6 +25,8 @@ + + diff --git a/Agent/Program.cs b/Agent/Program.cs index 8568d60a..4ad4e26d 100644 --- a/Agent/Program.cs +++ b/Agent/Program.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using System.Diagnostics; using System.Threading; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Remotely.Agent { @@ -24,9 +25,7 @@ namespace Remotely.Agent { try { - // TODO: Replace static services with scoped instances in IoC container. - var serviceCollection = new ServiceCollection(); - Services = serviceCollection.BuildServiceProvider(); + BuildServices(); Task.Run(() => { Init(args); }); @@ -39,6 +38,27 @@ namespace Remotely.Agent } } + private static void BuildServices() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddLogging(builder => + { + builder.AddConsole() + .AddEventLog(); + }); + serviceCollection.AddSingleton(); + serviceCollection.AddScoped(); + serviceCollection.AddScoped(); + serviceCollection.AddScoped(); + serviceCollection.AddScoped(); + serviceCollection.AddScoped(); + serviceCollection.AddScoped(); + serviceCollection.AddScoped(); + serviceCollection.AddScoped(); + + Services = serviceCollection.BuildServiceProvider(); + } + private static async void Init(string[] args) { AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; @@ -52,9 +72,9 @@ namespace Remotely.Agent if (argDict.ContainsKey("update")) { - Updater.CoreUpdate(); + Services.GetRequiredService().CoreUpdate(); } - + if (!IsDebug && OSUtils.IsWindows) { _ = Task.Run(() => @@ -65,7 +85,7 @@ namespace Remotely.Agent try { - await DeviceSocket.Connect(); + await Services.GetRequiredService().Connect(); } finally { @@ -79,12 +99,12 @@ namespace Remotely.Agent { try { - if (!DeviceSocket.IsConnected) + if (!Services.GetRequiredService().IsConnected) { var waitTime = new Random().Next(1000, 30000); Logger.Write($"Websocket closed. Reconnecting in {waitTime / 1000} seconds..."); await Task.Delay(waitTime); - await DeviceSocket.Connect(); + await Services.GetRequiredService().Connect(); } } catch (Exception ex) diff --git a/Agent/Services/Bash.cs b/Agent/Services/Bash.cs index ac5c809e..d2c70a3e 100644 --- a/Agent/Services/Bash.cs +++ b/Agent/Services/Bash.cs @@ -5,52 +5,15 @@ using System.Diagnostics; using System.Text; using System.Threading; using System.Collections.Concurrent; +using Microsoft.Extensions.DependencyInjection; namespace Remotely.Agent.Services { public class Bash { - private static ConcurrentDictionary Sessions { get; set; } = new ConcurrentDictionary(); - private Process BashProc { get; } - private System.Timers.Timer ProcessIdleTimeout { get; set; } - private string ConnectionID { get; set; } - private string LastInputID { get; set; } - private bool OutputDone { get; set; } - private string StandardOut { get; set; } - private string ErrorOut { get; set; } - - public static Bash GetCurrent(string connectionID) - { - if (Sessions.ContainsKey(connectionID)) - { - var bash = Sessions[connectionID]; - bash.ProcessIdleTimeout.Stop(); - bash.ProcessIdleTimeout.Start(); - return bash; - } - else - { - var bash = new Bash(); - bash.ConnectionID = connectionID; - bash.ProcessIdleTimeout = new System.Timers.Timer(600000); // 10 minutes. - bash.ProcessIdleTimeout.AutoReset = false; - bash.ProcessIdleTimeout.Elapsed += bash.ProcessIdleTimeout_Elapsed; - Sessions.AddOrUpdate(connectionID, bash, (id, b) => bash); - bash.ProcessIdleTimeout.Start(); - return bash; - } - } - - private void ProcessIdleTimeout_Elapsed(object sender, System.Timers.ElapsedEventArgs e) - { - Sessions.Remove(ConnectionID, out var outResult); - outResult.BashProc.Kill(); - } - - - - private Bash() + public Bash(ConfigService configService) { + ConfigService = configService; var psi = new ProcessStartInfo("bash"); psi.WindowStyle = ProcessWindowStyle.Hidden; psi.Verb = "RunAs"; @@ -68,26 +31,37 @@ namespace Remotely.Agent.Services BashProc.BeginErrorReadLine(); BashProc.BeginOutputReadLine(); + + ProcessIdleTimeout = new System.Timers.Timer(600_000); // 10 minutes. + ProcessIdleTimeout.AutoReset = false; + ProcessIdleTimeout.Elapsed += ProcessIdleTimeout_Elapsed; + ProcessIdleTimeout.Start(); } - private void CMDProc_OutputDataReceived(object sender, DataReceivedEventArgs e) + private static ConcurrentDictionary Sessions { get; set; } = new ConcurrentDictionary(); + private Process BashProc { get; } + private ConfigService ConfigService { get; set; } + private string ConnectionID { get; set; } + private string ErrorOut { get; set; } + private string LastInputID { get; set; } + private bool OutputDone { get; set; } + private System.Timers.Timer ProcessIdleTimeout { get; set; } + private string StandardOut { get; set; } + public static Bash GetCurrent(string connectionID) { - if (e?.Data?.Contains(LastInputID) == true) + if (Sessions.ContainsKey(connectionID)) { - OutputDone = true; + var bash = Sessions[connectionID]; + bash.ProcessIdleTimeout.Stop(); + bash.ProcessIdleTimeout.Start(); + return bash; } - else if (!OutputDone) + else { - StandardOut += e.Data + Environment.NewLine; - } - - } - - private void CMDProc_ErrorDataReceived(object sender, DataReceivedEventArgs e) - { - if (e?.Data != null) - { - ErrorOut += e.Data + Environment.NewLine; + var bash = Program.Services.GetRequiredService(); + bash.ConnectionID = connectionID; + Sessions.AddOrUpdate(connectionID, bash, (id, b) => bash); + return bash; } } @@ -114,21 +88,25 @@ namespace Remotely.Agent.Services return GenerateCompletedResult(); } - private GenericCommandResult GeneratePartialResult() + private void CMDProc_ErrorDataReceived(object sender, DataReceivedEventArgs e) { - OutputDone = true; - var partialResult = new GenericCommandResult() + if (e?.Data != null) { - CommandContextID = LastInputID, - DeviceID = ConfigService.GetConnectionInfo().DeviceID, - CommandType = "Bash", - StandardOutput = StandardOut, - ErrorOutput = "WARNING: The command execution froze and was forced to return before finishing. " + - "The results may be partial, and the console process has been reset. " + - "Please note that interactive commands aren't supported." + Environment.NewLine + ErrorOut - }; - ProcessIdleTimeout_Elapsed(this, null); - return partialResult; + ErrorOut += e.Data + Environment.NewLine; + } + } + + private void CMDProc_OutputDataReceived(object sender, DataReceivedEventArgs e) + { + if (e?.Data?.Contains(LastInputID) == true) + { + OutputDone = true; + } + else if (!OutputDone) + { + StandardOut += e.Data + Environment.NewLine; + } + } private GenericCommandResult GenerateCompletedResult() @@ -143,5 +121,27 @@ namespace Remotely.Agent.Services }; } + private GenericCommandResult GeneratePartialResult() + { + OutputDone = true; + var partialResult = new GenericCommandResult() + { + CommandContextID = LastInputID, + DeviceID = ConfigService.GetConnectionInfo().DeviceID, + CommandType = "Bash", + StandardOutput = StandardOut, + ErrorOutput = "WARNING: The command execution froze and was forced to return before finishing. " + + "The results may be partial, and the console process has been reset. " + + "Please note that interactive commands aren't supported." + Environment.NewLine + ErrorOut + }; + ProcessIdleTimeout_Elapsed(this, null); + return partialResult; + } + + private void ProcessIdleTimeout_Elapsed(object sender, System.Timers.ElapsedEventArgs e) + { + BashProc?.Kill(); + Sessions.TryRemove(ConnectionID, out _); + } } } diff --git a/Agent/Services/CMD.cs b/Agent/Services/CMD.cs index b038ab4f..cbf34e78 100644 --- a/Agent/Services/CMD.cs +++ b/Agent/Services/CMD.cs @@ -6,13 +6,15 @@ using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading; +using Microsoft.Extensions.DependencyInjection; namespace Remotely.Agent.Services { public class CMD { - private CMD() + public CMD(ConfigService configService) { + ConfigService = configService; var psi = new ProcessStartInfo("cmd.exe"); psi.WindowStyle = ProcessWindowStyle.Hidden; psi.Verb = "RunAs"; @@ -30,10 +32,16 @@ namespace Remotely.Agent.Services CMDProc.BeginErrorReadLine(); CMDProc.BeginOutputReadLine(); + + ProcessIdleTimeout = new System.Timers.Timer(600_000); // 10 minutes. + ProcessIdleTimeout.AutoReset = false; + ProcessIdleTimeout.Elapsed += ProcessIdleTimeout_Elapsed; + ProcessIdleTimeout.Start(); } private static ConcurrentDictionary Sessions { get; set; } = new ConcurrentDictionary(); private Process CMDProc { get; } + private ConfigService ConfigService { get; } private string ConnectionID { get; set; } private string ErrorOut { get; set; } @@ -52,13 +60,9 @@ namespace Remotely.Agent.Services } else { - var cmd = new CMD(); + var cmd = Program.Services.GetRequiredService(); cmd.ConnectionID = connectionID; - cmd.ProcessIdleTimeout = new System.Timers.Timer(600000); // 10 minutes. - cmd.ProcessIdleTimeout.AutoReset = false; - cmd.ProcessIdleTimeout.Elapsed += cmd.ProcessIdleTimeout_Elapsed; Sessions.AddOrUpdate(connectionID, cmd, (id, c) => cmd); - cmd.ProcessIdleTimeout.Start(); return cmd; } } @@ -139,8 +143,8 @@ namespace Remotely.Agent.Services private void ProcessIdleTimeout_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { - Sessions.Remove(ConnectionID, out var outResult); - outResult.CMDProc.Kill(); + CMDProc?.Kill(); + Sessions.TryRemove(ConnectionID, out _); } } } diff --git a/Agent/Services/ConfigService.cs b/Agent/Services/ConfigService.cs index 5c21cfd8..aba213fe 100644 --- a/Agent/Services/ConfigService.cs +++ b/Agent/Services/ConfigService.cs @@ -8,28 +8,36 @@ using System.Linq; namespace Remotely.Agent.Services { - public static class ConfigService + public class ConfigService { - private static ConnectionInfo connectionInfo; - public static ConnectionInfo GetConnectionInfo() + private static object fileLock = new object(); + private ConnectionInfo connectionInfo; + + public ConnectionInfo GetConnectionInfo() { if (connectionInfo == null) { - if (!File.Exists("ConnectionInfo.json")) + lock (fileLock) { - Logger.Write(new Exception("No connection info available. Please create ConnectionInfo.json file with appropriate values.")); - return null; + if (!File.Exists("ConnectionInfo.json")) + { + Logger.Write(new Exception("No connection info available. Please create ConnectionInfo.json file with appropriate values.")); + return null; + } + connectionInfo = JsonConvert.DeserializeObject(File.ReadAllText("ConnectionInfo.json")); } - connectionInfo = JsonConvert.DeserializeObject(File.ReadAllText("ConnectionInfo.json")); } return connectionInfo; } - public static void SaveConnectionInfo(ConnectionInfo connectionInfo) + public void SaveConnectionInfo(ConnectionInfo connectionInfo) { - File.WriteAllText("ConnectionInfo.json", JsonConvert.SerializeObject(connectionInfo)); + lock (fileLock) + { + File.WriteAllText("ConnectionInfo.json", JsonConvert.SerializeObject(connectionInfo)); + } } } } diff --git a/Agent/Services/DeviceSocket.cs b/Agent/Services/DeviceSocket.cs index cf08b793..2bbdb66e 100644 --- a/Agent/Services/DeviceSocket.cs +++ b/Agent/Services/DeviceSocket.cs @@ -17,15 +17,24 @@ using Microsoft.Extensions.DependencyInjection; namespace Remotely.Agent.Services { - public static class DeviceSocket + public class DeviceSocket { - public static Timer HeartbeatTimer { get; private set; } - public static bool IsServerVerified { get; set; } - private static ConnectionInfo ConnectionInfo { get; set; } + public DeviceSocket(Updater updater, ConfigService configService, Uninstaller uninstaller) + { + Updater = updater; + ConfigService = configService; + Uninstaller = uninstaller; + } + public Timer HeartbeatTimer { get; private set; } + public bool IsConnected => HubConnection?.State == HubConnectionState.Connected; + public bool IsServerVerified { get; set; } + public Uninstaller Uninstaller { get; } + private ConfigService ConfigService { get; } + private ConnectionInfo ConnectionInfo { get; set; } - private static HubConnection HubConnection { get; set; } - - public static async Task Connect() + private HubConnection HubConnection { get; set; } + private Updater Updater { get; } + public async Task Connect() { ConnectionInfo = ConfigService.GetConnectionInfo(); @@ -59,16 +68,13 @@ namespace Remotely.Agent.Services HeartbeatTimer.Elapsed += HeartbeatTimer_Elapsed; HeartbeatTimer.Start(); } - - public static bool IsConnected => HubConnection?.State == HubConnectionState.Connected; - - public static void SendHeartbeat() + public void SendHeartbeat() { var currentInfo = Device.Create(ConnectionInfo); HubConnection.InvokeAsync("DeviceHeartbeat", currentInfo); } - private static async Task ExecuteCommand(string mode, string command, string commandID, string senderConnectionID) + private async Task ExecuteCommand(string mode, string command, string commandID, string senderConnectionID) { if (!IsServerVerified) { @@ -150,16 +156,16 @@ namespace Remotely.Agent.Services catch (Exception ex) { Logger.Write(ex); - await HubConnection.InvokeAsync("DisplayMessage", $"There was an error executing the command. It has been logged on the client device.", "Error executing command.", senderConnectionID); + await HubConnection.InvokeAsync("DisplayMessage", "There was an error executing the command. It has been logged on the client device.", "Error executing command.", senderConnectionID); } } - private static void HeartbeatTimer_Elapsed(object sender, ElapsedEventArgs e) + private void HeartbeatTimer_Elapsed(object sender, ElapsedEventArgs e) { SendHeartbeat(); } - private static void RegisterMessageHandlers(HubConnection hubConnection) + private void RegisterMessageHandlers(HubConnection hubConnection) { hubConnection.On("ExecuteCommand", (async (string mode, string command, string commandID, string senderConnectionID) => { @@ -263,8 +269,6 @@ namespace Remotely.Agent.Services } else if (OSUtils.IsLinux) { - //var users = OSUtils.StartProcessWithResults("users", ""); - //var username = users?.Split()?.FirstOrDefault()?.Trim(); var xauthority = OSUtils.StartProcessWithResults("find", $"/ -name Xauthority").Split('\n', StringSplitOptions.RemoveEmptyEntries).First(); var display = ":0"; var whoString = OSUtils.StartProcessWithResults("who", "")?.Trim(); @@ -387,7 +391,7 @@ namespace Remotely.Agent.Services }); } - private static void SendResultsViaAjax(string resultType, object result) + private void SendResultsViaAjax(string resultType, object result) { var targetURL = ConfigService.GetConnectionInfo().Host + $"/API/Commands/{resultType}"; var webRequest = WebRequest.CreateHttp(targetURL); diff --git a/Agent/Services/Logger.cs b/Agent/Services/Logger.cs index f10caed8..d95868aa 100644 --- a/Agent/Services/Logger.cs +++ b/Agent/Services/Logger.cs @@ -10,7 +10,7 @@ using System.Threading.Tasks; namespace Remotely.Agent.Services { - public static class Logger + public class Logger { private static string LogPath => Path.Combine(Path.GetTempPath(), "Remotely_Logs.log"); private static object WriteLock { get; } = new object(); diff --git a/Agent/Services/PSCore.cs b/Agent/Services/PSCore.cs index 0f16691e..aa4a0288 100644 --- a/Agent/Services/PSCore.cs +++ b/Agent/Services/PSCore.cs @@ -7,13 +7,38 @@ using System.Linq; using System.Management.Automation; using System.Text; using System.Timers; +using Microsoft.Extensions.DependencyInjection; namespace Remotely.Agent.Services { public class PSCore { + public PSCore(ConfigService configService) + { + ConfigService = configService; + PS = PowerShell.Create(); + PS.AddScript(@"$VerbosePreference = ""Continue""; + $DebugPreference = ""Continue""; + $InformationPreference = ""Continue""; + $WarningPreference = ""Continue"";"); + PS.Invoke(); + + ProcessIdleTimeout = new Timer(600_000); // 10 minutes. + ProcessIdleTimeout.AutoReset = false; + ProcessIdleTimeout.Elapsed += ProcessIdleTimeout_Elapsed; + ProcessIdleTimeout.Start(); + } + + public string ConnectionID { get; private set; } + private static ConcurrentDictionary Sessions { get; set; } = new ConcurrentDictionary(); + + private ConfigService ConfigService { get; } + private Timer ProcessIdleTimeout { get; set; } + + private PowerShell PS { get; set; } + public static PSCore GetCurrent(string connectionID) { if (Sessions.ContainsKey(connectionID)) @@ -25,36 +50,19 @@ namespace Remotely.Agent.Services } else { - var psCore = new PSCore(); - psCore.ProcessIdleTimeout = new Timer(600000); // 10 minutes. - psCore.ProcessIdleTimeout.AutoReset = false; - psCore.ProcessIdleTimeout.Elapsed += (sender, args) => - { - Sessions.Remove(connectionID, out var pSCore); - }; + var psCore = Program.Services.GetRequiredService(); + psCore.ConnectionID = connectionID; Sessions.AddOrUpdate(connectionID, psCore, (id, p) => psCore); - psCore.ProcessIdleTimeout.Start(); return psCore; } } - private PowerShell PS { get; set; } - - private PSCore() - { - PS = PowerShell.Create(); - PS.AddScript(@"$VerbosePreference = ""Continue""; - $DebugPreference = ""Continue""; - $InformationPreference = ""Continue""; - $WarningPreference = ""Continue"";"); - PS.Invoke(); - } public PSCoreCommandResult WriteInput(string input, string commandID) { PS.Commands.Clear(); PS.AddScript(input); var results = PS.Invoke(); - + var ps = PowerShell.Create(); ps.AddScript("$args[0] | Out-String"); ps.AddArgument(results); @@ -68,7 +76,7 @@ namespace Remotely.Agent.Services PS.Streams.ClearStreams(); PS.Commands.Clear(); - + return new PSCoreCommandResult() { CommandContextID = commandID, @@ -82,5 +90,10 @@ namespace Remotely.Agent.Services }; } + private void ProcessIdleTimeout_Elapsed(object sender, ElapsedEventArgs e) + { + PS?.Dispose(); + Sessions.TryRemove(ConnectionID, out _); + } } } diff --git a/Agent/Services/Uninstaller.cs b/Agent/Services/Uninstaller.cs index 2b13b2ca..bf4fd8c4 100644 --- a/Agent/Services/Uninstaller.cs +++ b/Agent/Services/Uninstaller.cs @@ -11,7 +11,7 @@ namespace Remotely.Agent.Services { public class Uninstaller { - public static void UninstallAgent() + public void UninstallAgent() { if (OSUtils.IsWindows) { diff --git a/Agent/Services/Updater.cs b/Agent/Services/Updater.cs index ad00c00d..44a1e3fa 100644 --- a/Agent/Services/Updater.cs +++ b/Agent/Services/Updater.cs @@ -15,7 +15,14 @@ namespace Remotely.Agent.Services { public class Updater { - internal static void CheckForCoreUpdates() + public Updater(ConfigService configService) + { + ConfigService = configService; + } + + private ConfigService ConfigService { get; } + + public void CheckForCoreUpdates() { try { @@ -69,7 +76,7 @@ namespace Remotely.Agent.Services Logger.Write(ex); } } - internal static void CoreUpdate() + public void CoreUpdate() { try { @@ -172,23 +179,5 @@ namespace Remotely.Agent.Services Environment.Exit(0); } } - internal static async Task GetLatestScreenCastVersion() - { - var platform = ""; - if (OSUtils.IsWindows) - { - platform = "Windows"; - } - else if (OSUtils.IsLinux) - { - platform = "Linux"; - } - else - { - throw new Exception("Unsupported operating system."); - } - var response = await new HttpClient().GetAsync(ConfigService.GetConnectionInfo().Host + $"/API/ScreenCastVersion/{platform}"); - return await response.Content.ReadAsStringAsync(); - } } } diff --git a/Agent/Services/WindowsPS.cs b/Agent/Services/WindowsPS.cs index 5ec7fb3e..52c23c23 100644 --- a/Agent/Services/WindowsPS.cs +++ b/Agent/Services/WindowsPS.cs @@ -1,4 +1,5 @@ -using Remotely.Shared.Models; +using Microsoft.Extensions.DependencyInjection; +using Remotely.Shared.Models; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -10,45 +11,9 @@ namespace Remotely.Agent.Services { public class WindowsPS { - private static ConcurrentDictionary Sessions { get; set; } = new ConcurrentDictionary(); - private string ConnectionID { get; set; } - private System.Timers.Timer ProcessIdleTimeout { get; set; } - private string LastInputID { get; set; } - private bool OutputDone { get; set; } - private string StandardOut { get; set; } - private string ErrorOut { get; set; } - public static WindowsPS GetCurrent(string connectionID) - { - if (Sessions.ContainsKey(connectionID)) - { - var winPS = Sessions[connectionID]; - winPS.ProcessIdleTimeout.Stop(); - winPS.ProcessIdleTimeout.Start(); - return winPS; - } - else - { - var winPS = new WindowsPS(); - winPS.ConnectionID = connectionID; - winPS.ProcessIdleTimeout = new System.Timers.Timer(600000); // 10 minutes. - winPS.ProcessIdleTimeout.AutoReset = false; - winPS.ProcessIdleTimeout.Elapsed += winPS.ProcessIdleTimeout_Elapsed; - Sessions.AddOrUpdate(connectionID, winPS, (id, w) => winPS); - winPS.ProcessIdleTimeout.Start(); - return winPS; - } - } - - private void ProcessIdleTimeout_Elapsed(object sender, System.Timers.ElapsedEventArgs e) - { - Sessions.Remove(ConnectionID, out var outResult); - outResult.PSProc.Kill(); - } - - private Process PSProc { get; } - - private WindowsPS() + public WindowsPS(ConfigService configService) { + ConfigService = configService; var psi = new ProcessStartInfo("powershell.exe"); psi.WindowStyle = ProcessWindowStyle.Hidden; psi.Verb = "RunAs"; @@ -66,25 +31,38 @@ namespace Remotely.Agent.Services PSProc.BeginErrorReadLine(); PSProc.BeginOutputReadLine(); + + ProcessIdleTimeout = new System.Timers.Timer(600_000); // 10 minutes. + ProcessIdleTimeout.AutoReset = false; + ProcessIdleTimeout.Elapsed += ProcessIdleTimeout_Elapsed; + ProcessIdleTimeout.Start(); } - private void CMDProc_OutputDataReceived(object sender, DataReceivedEventArgs e) + private static ConcurrentDictionary Sessions { get; set; } = new ConcurrentDictionary(); + private ConfigService ConfigService { get; } + private string ConnectionID { get; set; } + private string ErrorOut { get; set; } + private string LastInputID { get; set; } + private bool OutputDone { get; set; } + private System.Timers.Timer ProcessIdleTimeout { get; set; } + private Process PSProc { get; } + private string StandardOut { get; set; } + public static WindowsPS GetCurrent(string connectionID) { - if (e?.Data?.Contains(LastInputID) == true) + if (Sessions.ContainsKey(connectionID)) { - OutputDone = true; + var winPS = Sessions[connectionID]; + winPS.ProcessIdleTimeout.Stop(); + winPS.ProcessIdleTimeout.Start(); + return winPS; } - else if (!OutputDone) + else { - StandardOut += e.Data + Environment.NewLine; - } - } + var winPS = Program.Services.GetRequiredService(); - private void CMDProc_ErrorDataReceived(object sender, DataReceivedEventArgs e) - { - if (e?.Data != null) - { - ErrorOut += e.Data + Environment.NewLine; + winPS.ConnectionID = connectionID; + Sessions.AddOrUpdate(connectionID, winPS, (id, w) => winPS); + return winPS; } } @@ -112,6 +90,38 @@ namespace Remotely.Agent.Services return GenerateCompletedResult(); } + private void CMDProc_ErrorDataReceived(object sender, DataReceivedEventArgs e) + { + if (e?.Data != null) + { + ErrorOut += e.Data + Environment.NewLine; + } + } + + private void CMDProc_OutputDataReceived(object sender, DataReceivedEventArgs e) + { + if (e?.Data?.Contains(LastInputID) == true) + { + OutputDone = true; + } + else if (!OutputDone) + { + StandardOut += e.Data + Environment.NewLine; + } + } + + private GenericCommandResult GenerateCompletedResult() + { + return new GenericCommandResult() + { + CommandContextID = LastInputID, + DeviceID = ConfigService.GetConnectionInfo().DeviceID, + CommandType = "WinPS", + StandardOutput = StandardOut, + ErrorOutput = ErrorOut + }; + } + private GenericCommandResult GeneratePartialResult() { OutputDone = true; @@ -129,16 +139,10 @@ namespace Remotely.Agent.Services return partialResult; } - private GenericCommandResult GenerateCompletedResult() + private void ProcessIdleTimeout_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { - return new GenericCommandResult() - { - CommandContextID = LastInputID, - DeviceID = ConfigService.GetConnectionInfo().DeviceID, - CommandType = "WinPS", - StandardOutput = StandardOut, - ErrorOutput = ErrorOut - }; + PSProc?.Kill(); + Sessions.TryRemove(ConnectionID, out _); } } } diff --git a/Desktop.Linux/Desktop.Linux.csproj b/Desktop.Linux/Desktop.Linux.csproj index a407431b..2ea9a573 100644 --- a/Desktop.Linux/Desktop.Linux.csproj +++ b/Desktop.Linux/Desktop.Linux.csproj @@ -35,9 +35,9 @@ - - - + + +