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 @@
-
-
-
+
+
+