mirror of
https://github.com/immense/Remotely.git
synced 2025-10-26 11:27:15 +00:00
Sync Remotely with latest integration changes.
This commit is contained in:
parent
0fa41e879f
commit
bb2126bbab
@ -380,7 +380,6 @@ namespace Remotely.Agent.Installer.Win.Services
|
||||
Description = "Background service that maintains a connection to the Remotely server. The service is used for remote support and maintenance by this computer's administrators.",
|
||||
ServiceName = "Remotely_Service",
|
||||
StartType = ServiceStartMode.Automatic,
|
||||
DelayedAutoStart = true,
|
||||
Parent = new ServiceProcessInstaller()
|
||||
};
|
||||
|
||||
|
||||
@ -15,6 +15,5 @@ namespace Remotely.Agent.Interfaces
|
||||
(double usedGB, double totalGB) GetMemoryInGB();
|
||||
string GetAgentVersion();
|
||||
List<Drive> GetAllDrives();
|
||||
Task<double> GetCpuUtilization();
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.ServiceProcess;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Runtime.Versioning;
|
||||
using Remotely.Agent.Services.Linux;
|
||||
@ -55,6 +54,8 @@ namespace Remotely.Agent
|
||||
|
||||
// TODO: All these should be registered as interfaces.
|
||||
serviceCollection.AddSingleton<IAgentHubConnection, AgentHubConnection>();
|
||||
serviceCollection.AddSingleton<ICpuUtilizationSampler, CpuUtilizationSampler>();
|
||||
serviceCollection.AddHostedService(services => services.GetRequiredService<ICpuUtilizationSampler>());
|
||||
serviceCollection.AddScoped<ChatClientService>();
|
||||
serviceCollection.AddTransient<PSCore>();
|
||||
serviceCollection.AddTransient<ExternalScriptingShell>();
|
||||
|
||||
@ -489,10 +489,7 @@ namespace Remotely.Agent.Services
|
||||
}
|
||||
});
|
||||
|
||||
_hubConnection.On("TriggerHeartbeat", async () =>
|
||||
{
|
||||
await SendHeartbeat().ConfigureAwait(false);
|
||||
});
|
||||
_hubConnection.On("TriggerHeartbeat", SendHeartbeat);
|
||||
}
|
||||
|
||||
private async Task<bool> VerifyServer()
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@ -9,24 +10,36 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Remotely.Agent.Services;
|
||||
|
||||
|
||||
internal interface ICpuUtilizationSampler : IHostedService
|
||||
public interface ICpuUtilizationSampler : IHostedService
|
||||
{
|
||||
double CurrentUtilization { get; }
|
||||
}
|
||||
|
||||
internal class CpuUtilizationSampler : BackgroundService, ICpuUtilizationSampler
|
||||
{
|
||||
private readonly ILogger<CpuUtilizationSampler> _logger;
|
||||
private double _currentUtilization;
|
||||
|
||||
public CpuUtilizationSampler(ILogger<CpuUtilizationSampler> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public double CurrentUtilization => _currentUtilization;
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
var currentUtil = await GetCpuUtilization(stoppingToken);
|
||||
Interlocked.Exchange(ref _currentUtilization, currentUtil);
|
||||
try
|
||||
{
|
||||
var currentUtil = await GetCpuUtilization(stoppingToken);
|
||||
Interlocked.Exchange(ref _currentUtilization, currentUtil);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error while getting CPU utilization sample.");
|
||||
}
|
||||
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Remotely.Shared.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Remotely.Shared.Models;
|
||||
using Remotely.Shared.Services;
|
||||
using Remotely.Shared.Utilities;
|
||||
using System;
|
||||
@ -14,6 +15,13 @@ namespace Remotely.Agent.Services
|
||||
{
|
||||
public class DeviceInfoGeneratorBase
|
||||
{
|
||||
protected readonly ILogger<DeviceInfoGeneratorBase> _logger;
|
||||
|
||||
public DeviceInfoGeneratorBase(ILogger<DeviceInfoGeneratorBase> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Device GetDeviceBase(string deviceID, string orgID)
|
||||
{
|
||||
|
||||
@ -63,7 +71,7 @@ namespace Remotely.Agent.Services
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Write(ex, "Error getting system drive info.");
|
||||
_logger.LogError(ex, "Error getting system drive info.");
|
||||
}
|
||||
|
||||
return (0, 0);
|
||||
@ -80,7 +88,7 @@ namespace Remotely.Agent.Services
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Write(ex, "Error getting agent version.");
|
||||
_logger.LogError(ex, "Error getting agent version.");
|
||||
}
|
||||
|
||||
return "0.0.0.0";
|
||||
@ -103,55 +111,9 @@ namespace Remotely.Agent.Services
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Write(ex, "Error getting drive info.");
|
||||
_logger.LogError(ex, "Error getting drive info.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<double> GetCpuUtilization()
|
||||
{
|
||||
double totalUtilization = 0;
|
||||
var utilizations = new Dictionary<int, Tuple<DateTimeOffset, TimeSpan>>();
|
||||
var processes = Process.GetProcesses();
|
||||
|
||||
foreach (var proc in processes)
|
||||
{
|
||||
try
|
||||
{
|
||||
var startTime = DateTimeOffset.Now;
|
||||
var startCpuUsage = proc.TotalProcessorTime;
|
||||
utilizations.Add(proc.Id, new Tuple<DateTimeOffset, TimeSpan>(startTime, startCpuUsage));
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
foreach (var kvp in utilizations)
|
||||
{
|
||||
var endTime = DateTimeOffset.Now;
|
||||
try
|
||||
{
|
||||
var proc = Process.GetProcessById(kvp.Key);
|
||||
var startTime = kvp.Value.Item1;
|
||||
var startCpuUsage = kvp.Value.Item2;
|
||||
var endCpuUsage = proc.TotalProcessorTime;
|
||||
var cpuUsedMs = (endCpuUsage - startCpuUsage).TotalMilliseconds;
|
||||
var totalMsPassed = (endTime - startTime).TotalMilliseconds;
|
||||
var cpuUsageTotal = cpuUsedMs / (Environment.ProcessorCount * totalMsPassed);
|
||||
totalUtilization += cpuUsageTotal;
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return totalUtilization;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Remotely.Agent.Interfaces;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Remotely.Agent.Interfaces;
|
||||
using Remotely.Shared.Models;
|
||||
using Remotely.Shared.Services;
|
||||
using Remotely.Shared.Utilities;
|
||||
@ -13,12 +14,19 @@ namespace Remotely.Agent.Services.Linux
|
||||
public class DeviceInfoGeneratorLinux : DeviceInfoGeneratorBase, IDeviceInformationService
|
||||
{
|
||||
private readonly IProcessInvoker _processInvoker;
|
||||
private readonly ICpuUtilizationSampler _cpuUtilSampler;
|
||||
|
||||
public DeviceInfoGeneratorLinux(IProcessInvoker processInvoker)
|
||||
public DeviceInfoGeneratorLinux(
|
||||
IProcessInvoker processInvoker,
|
||||
ICpuUtilizationSampler cpuUtilSampler,
|
||||
ILogger<DeviceInfoGeneratorLinux> logger)
|
||||
: base(logger)
|
||||
{
|
||||
_processInvoker = processInvoker;
|
||||
_cpuUtilSampler = cpuUtilSampler;
|
||||
}
|
||||
public async Task<Device> CreateDevice(string deviceId, string orgId)
|
||||
|
||||
public Task<Device> CreateDevice(string deviceId, string orgId)
|
||||
{
|
||||
var device = GetDeviceBase(deviceId, orgId);
|
||||
|
||||
@ -34,15 +42,15 @@ namespace Remotely.Agent.Services.Linux
|
||||
device.TotalStorage = totalStorage;
|
||||
device.UsedMemory = usedMemory;
|
||||
device.TotalMemory = totalMemory;
|
||||
device.CpuUtilization = await GetCpuUtilization();
|
||||
device.CpuUtilization = _cpuUtilSampler.CurrentUtilization;
|
||||
device.AgentVersion = GetAgentVersion();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Write(ex, "Error getting device info.");
|
||||
_logger.LogError(ex, "Error getting device info.");
|
||||
}
|
||||
|
||||
return device;
|
||||
return Task.FromResult(device);
|
||||
}
|
||||
|
||||
private string GetCurrentUser()
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Remotely.Agent.Interfaces;
|
||||
using Remotely.Shared.Models;
|
||||
using Remotely.Shared.Services;
|
||||
@ -15,7 +16,8 @@ namespace Remotely.Agent.Services.MacOS
|
||||
{
|
||||
private readonly IProcessInvoker _processInvoker;
|
||||
|
||||
public DeviceInfoGeneratorMac(IProcessInvoker processInvoker)
|
||||
public DeviceInfoGeneratorMac(IProcessInvoker processInvoker, ILogger<DeviceInfoGeneratorMac> logger)
|
||||
: base(logger)
|
||||
{
|
||||
_processInvoker = processInvoker;
|
||||
}
|
||||
@ -40,40 +42,12 @@ namespace Remotely.Agent.Services.MacOS
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Write(ex, "Error getting device info.");
|
||||
_logger.LogError(ex, "Error getting device info.");
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
public new Task<double> GetCpuUtilization()
|
||||
{
|
||||
try
|
||||
{
|
||||
var cpuPercentStrings = _processInvoker.InvokeProcessOutput("zsh", "-c \"ps -A -o %cpu\"");
|
||||
|
||||
double cpuPercent = 0;
|
||||
cpuPercentStrings
|
||||
.Split(Environment.NewLine)
|
||||
.ToList()
|
||||
.ForEach(x =>
|
||||
{
|
||||
if (double.TryParse(x, out var result))
|
||||
{
|
||||
cpuPercent += result;
|
||||
}
|
||||
});
|
||||
|
||||
return Task.FromResult(cpuPercent / Environment.ProcessorCount / 100);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Write(ex, "Error while getting CPU utilization.");
|
||||
}
|
||||
|
||||
return Task.FromResult((double)0);
|
||||
}
|
||||
|
||||
public (double usedGB, double totalGB) GetMemoryInGB()
|
||||
{
|
||||
try
|
||||
@ -114,6 +88,33 @@ namespace Remotely.Agent.Services.MacOS
|
||||
}
|
||||
}
|
||||
|
||||
private Task<double> GetCpuUtilization()
|
||||
{
|
||||
try
|
||||
{
|
||||
var cpuPercentStrings = _processInvoker.InvokeProcessOutput("zsh", "-c \"ps -A -o %cpu\"");
|
||||
|
||||
double cpuPercent = 0;
|
||||
cpuPercentStrings
|
||||
.Split(Environment.NewLine)
|
||||
.ToList()
|
||||
.ForEach(x =>
|
||||
{
|
||||
if (double.TryParse(x, out var result))
|
||||
{
|
||||
cpuPercent += result;
|
||||
}
|
||||
});
|
||||
|
||||
return Task.FromResult(cpuPercent / Environment.ProcessorCount / 100);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error while getting CPU utilization.");
|
||||
}
|
||||
|
||||
return Task.FromResult((double)0);
|
||||
}
|
||||
private string GetCurrentUser()
|
||||
{
|
||||
var users = _processInvoker.InvokeProcessOutput("users", "");
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Remotely.Agent.Interfaces;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Remotely.Agent.Interfaces;
|
||||
using Remotely.Shared.Models;
|
||||
using Remotely.Shared.Utilities;
|
||||
using Remotely.Shared.Win32;
|
||||
@ -12,7 +13,17 @@ namespace Remotely.Agent.Services.Windows
|
||||
{
|
||||
public class DeviceInfoGeneratorWin : DeviceInfoGeneratorBase, IDeviceInformationService
|
||||
{
|
||||
public async Task<Device> CreateDevice(string deviceId, string orgId)
|
||||
private readonly ICpuUtilizationSampler _cpuUtilSampler;
|
||||
|
||||
public DeviceInfoGeneratorWin(
|
||||
ICpuUtilizationSampler cpuUtilSampler,
|
||||
ILogger<DeviceInfoGeneratorWin> logger)
|
||||
: base(logger)
|
||||
{
|
||||
_cpuUtilSampler = cpuUtilSampler;
|
||||
}
|
||||
|
||||
public Task<Device> CreateDevice(string deviceId, string orgId)
|
||||
{
|
||||
var device = GetDeviceBase(deviceId, orgId);
|
||||
|
||||
@ -28,15 +39,15 @@ namespace Remotely.Agent.Services.Windows
|
||||
device.TotalStorage = totalStorage;
|
||||
device.UsedMemory = usedMemory;
|
||||
device.TotalMemory = totalMemory;
|
||||
device.CpuUtilization = await GetCpuUtilization();
|
||||
device.CpuUtilization = _cpuUtilSampler.CurrentUtilization;
|
||||
device.AgentVersion = GetAgentVersion();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Write(ex, "Error getting device info.");
|
||||
_logger.LogError(ex, "Error getting device info.");
|
||||
}
|
||||
|
||||
return device;
|
||||
return Task.FromResult(device);
|
||||
}
|
||||
|
||||
public (double usedGB, double totalGB) GetMemoryInGB()
|
||||
|
||||
@ -66,11 +66,12 @@ if (appState.ArgDict.TryGetValue("org-id", out var orgId))
|
||||
var result = await provider.UseRemoteControlClient(
|
||||
args,
|
||||
"The remote control client for Remotely.",
|
||||
serverUrl);
|
||||
serverUrl,
|
||||
false);
|
||||
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
logger.LogError(result.Exception, "Failed to remote control client.");
|
||||
logger.LogError(result.Exception, "Failed to start remote control client.");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
<TargetFramework>.net7.0</TargetFramework>
|
||||
<PublishDir>..\Agent\bin\Release\.net7.0\linux-x64\publish\Desktop</PublishDir>
|
||||
<PublishDir>..\Agent\bin\Release\net7.0\linux-x64\publish\Desktop</PublishDir>
|
||||
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>False</PublishSingleFile>
|
||||
|
||||
@ -60,7 +60,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
<Exec Command="if $(SolutionDir) == *Undefined* (
 exit 0
)
if $(ConfigurationName) == Debug (
 if $(PlatformName) == AnyCPU (
 md "$(SolutionDir)Agent\bin\Debug\.net7.0\Desktop\"
 xcopy "$(TargetDir)*" "$(SolutionDir)Agent\bin\Debug\.net7.0\Desktop\" /y /e /i
 )
 if $(PlatformName) == x64 (
 md "$(SolutionDir)Agent\bin\x64\Debug\.net7.0\Desktop\"
 xcopy "$(TargetDir)*" "$(SolutionDir)Agent\bin\x64\Debug\.net7.0\Desktop\" /y /e /i
 )
 if $(PlatformName) == x86 (
 md "$(SolutionDir)Agent\bin\x86\Debug\.net7.0\Desktop\"
 xcopy "$(TargetDir)*" "$(SolutionDir)Agent\bin\x86\Debug\.net7.0\Desktop\" /y /e /i
 )
)" />
|
||||
<Exec Command="if $(SolutionDir) == *Undefined* (
 exit 0
)
if $(ConfigurationName) == Debug (
 if $(PlatformName) == AnyCPU (
 md "$(SolutionDir)Agent\bin\Debug\net7.0\Desktop\"
 xcopy "$(TargetDir)*" "$(SolutionDir)Agent\bin\Debug\net7.0\Desktop\" /y /e /i
 )
 if $(PlatformName) == x64 (
 md "$(SolutionDir)Agent\bin\x64\Debug\net7.0\Desktop\"
 xcopy "$(TargetDir)*" "$(SolutionDir)Agent\bin\x64\Debug\net7.0\Desktop\" /y /e /i
 )
 if $(PlatformName) == x86 (
 md "$(SolutionDir)Agent\bin\x86\Debug\net7.0\Desktop\"
 xcopy "$(TargetDir)*" "$(SolutionDir)Agent\bin\x86\Debug\net7.0\Desktop\" /y /e /i
 )
)" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
@ -66,11 +66,12 @@ if (appState.ArgDict.TryGetValue("org-id", out var orgId))
|
||||
var result = await provider.UseRemoteControlClient(
|
||||
args,
|
||||
"The remote control client for Remotely.",
|
||||
serverUrl);
|
||||
serverUrl,
|
||||
false);
|
||||
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
logger.LogError(result.Exception, "Failed to remote control client.");
|
||||
logger.LogError(result.Exception, "Failed to start remote control client.");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
<TargetFramework>.net7.0-windows</TargetFramework>
|
||||
<PublishDir>..\Agent\bin\Release\.net7.0\win10-x64\publish\Desktop</PublishDir>
|
||||
<PublishDir>..\Agent\bin\Release\net7.0\win10-x64\publish\Desktop</PublishDir>
|
||||
<SelfContained>true</SelfContained>
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<PublishSingleFile>True</PublishSingleFile>
|
||||
|
||||
@ -8,7 +8,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
<TargetFramework>.net7.0-windows</TargetFramework>
|
||||
<PublishDir>..\Agent\bin\Release\.net7.0\win10-x64\publish\Desktop</PublishDir>
|
||||
<PublishDir>..\Agent\bin\Release\net7.0\win10-x64\publish\Desktop</PublishDir>
|
||||
<SelfContained>true</SelfContained>
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<PublishSingleFile>False</PublishSingleFile>
|
||||
|
||||
@ -8,7 +8,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x86</Platform>
|
||||
<TargetFramework>.net7.0-windows</TargetFramework>
|
||||
<PublishDir>..\Agent\bin\Release\.net7.0\win10-x86\publish\Desktop</PublishDir>
|
||||
<PublishDir>..\Agent\bin\Release\net7.0\win10-x86\publish\Desktop</PublishDir>
|
||||
<RuntimeIdentifier>win10-x86</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>False</PublishSingleFile>
|
||||
|
||||
@ -49,11 +49,14 @@ namespace Remotely.Server.API
|
||||
if (HttpContext?.User?.Identity?.IsAuthenticated == true)
|
||||
{
|
||||
orgId = _dataService.GetUserByNameWithOrg(HttpContext.User.Identity.Name)?.OrganizationID;
|
||||
var activeSessions = _desktopSessionCache.Sessions.Where(x => x.Value.RequesterUserName == HttpContext.User.Identity.Name);
|
||||
foreach (var session in activeSessions.ToList())
|
||||
var activeSessions = _desktopSessionCache
|
||||
.Sessions
|
||||
.Where(x => x.RequesterUserName == HttpContext.User.Identity.Name);
|
||||
|
||||
foreach (var session in activeSessions)
|
||||
{
|
||||
await _desktopHub.Clients.Client(session.Value.DesktopConnectionId).SendAsync("Disconnect", "User logged out.");
|
||||
await _viewerHub.Clients.Clients(session.Value.ViewerList).SendAsync("ConnectionFailed");
|
||||
await _desktopHub.Clients.Client(session.DesktopConnectionId).SendAsync("Disconnect", "User logged out.");
|
||||
await _viewerHub.Clients.Clients(session.ViewerList).SendAsync("ConnectionFailed");
|
||||
}
|
||||
}
|
||||
await _signInManager.SignOutAsync();
|
||||
|
||||
@ -29,7 +29,7 @@ namespace Remotely.Server.API
|
||||
private readonly IServiceHubSessionCache _serviceSessionCache;
|
||||
private readonly IApplicationConfig _appConfig;
|
||||
private readonly IOtpProvider _otpProvider;
|
||||
private readonly IHubEventHandlerEx _hubEvents;
|
||||
private readonly IHubEventHandler _hubEvents;
|
||||
private readonly IDataService _dataService;
|
||||
private readonly SignInManager<RemotelyUser> _signInManager;
|
||||
|
||||
@ -40,7 +40,7 @@ namespace Remotely.Server.API
|
||||
IHubContext<AgentHub> serviceHub,
|
||||
IServiceHubSessionCache serviceSessionCache,
|
||||
IOtpProvider otpProvider,
|
||||
IHubEventHandlerEx hubEvents,
|
||||
IHubEventHandler hubEvents,
|
||||
IApplicationConfig appConfig)
|
||||
{
|
||||
_dataService = dataService;
|
||||
@ -112,7 +112,7 @@ namespace Remotely.Server.API
|
||||
}
|
||||
|
||||
|
||||
var sessionCount = _desktopSessionCache.Sessions.Values
|
||||
var sessionCount = _desktopSessionCache.Sessions
|
||||
.OfType<RemoteControlSessionEx>()
|
||||
.Count(x => x.OrganizationId == orgID);
|
||||
|
||||
@ -121,7 +121,7 @@ namespace Remotely.Server.API
|
||||
return BadRequest("There are already the maximum amount of active remote control sessions for your organization.");
|
||||
}
|
||||
|
||||
var sessionId = Guid.NewGuid().ToString();
|
||||
var sessionId = Guid.NewGuid();
|
||||
var accessKey = RandomGenerator.GenerateAccessKey();
|
||||
|
||||
var session = new RemoteControlSessionEx()
|
||||
@ -133,33 +133,32 @@ namespace Remotely.Server.API
|
||||
OrganizationId = orgID
|
||||
};
|
||||
|
||||
_desktopSessionCache.Sessions.AddOrUpdate(sessionId, session, (k, v) =>
|
||||
_desktopSessionCache.AddOrUpdate($"{sessionId}", session, (k, v) =>
|
||||
{
|
||||
if (v is RemoteControlSessionEx ex)
|
||||
{
|
||||
ex.ServiceConnectionId = HttpContext.Connection.Id;
|
||||
return ex;
|
||||
}
|
||||
v.Dispose();
|
||||
return session;
|
||||
});
|
||||
|
||||
var orgName = _dataService.GetOrganizationNameById(orgID);
|
||||
Task CreateSessionFunc()
|
||||
{
|
||||
return _serviceHub.Clients.Client(serviceConnectionId).SendAsync("RemoteControl",
|
||||
sessionId,
|
||||
accessKey,
|
||||
HttpContext.Connection.Id,
|
||||
string.Empty,
|
||||
orgName);
|
||||
|
||||
}
|
||||
await _serviceHub.Clients.Client(serviceConnectionId).SendAsync("RemoteControl",
|
||||
sessionId,
|
||||
accessKey,
|
||||
HttpContext.Connection.Id,
|
||||
string.Empty,
|
||||
orgName);
|
||||
|
||||
if (!await _hubEvents.TryWaitForSession(sessionId, CreateSessionFunc))
|
||||
var waitResult = await session.WaitForSessionReady(TimeSpan.FromSeconds(30));
|
||||
if (!waitResult)
|
||||
{
|
||||
return StatusCode(408, "The remote control process failed to start in time on the remote device.");
|
||||
}
|
||||
|
||||
|
||||
var otp = _otpProvider.GetOtp(targetDevice.ID);
|
||||
|
||||
return Ok($"{HttpContext.Request.Scheme}://{Request.Host}/RemoteControl/Viewer?mode=Unattended&sessionId={sessionId}&accessKey={accessKey}&otp={otp}");
|
||||
|
||||
@ -16,11 +16,11 @@
|
||||
{
|
||||
if (SignInManager.IsSignedIn(User))
|
||||
{
|
||||
var activeSessions = DesktopSessionCache.Sessions.Where(x => x.Value.RequesterUserName == HttpContext.User.Identity.Name);
|
||||
var activeSessions = DesktopSessionCache.Sessions.Where(x => x.RequesterUserName == HttpContext.User.Identity.Name);
|
||||
foreach (var session in activeSessions)
|
||||
{
|
||||
await DesktopHubContext.Clients.Client(session.Value.DesktopConnectionId).SendAsync("Disconnect", "User logged out.");
|
||||
await ViewerHubContext.Clients.Clients(session.Value.ViewerList).SendAsync("ConnectionFailed");
|
||||
await DesktopHubContext.Clients.Client(session.DesktopConnectionId).SendAsync("Disconnect", "User logged out.");
|
||||
await ViewerHubContext.Clients.Clients(session.ViewerList).SendAsync("ConnectionFailed");
|
||||
}
|
||||
|
||||
await SignInManager.SignOutAsync();
|
||||
|
||||
@ -268,15 +268,34 @@ namespace Remotely.Server.Components.Devices
|
||||
AppState.InvokePropertyChanged(nameof(AppState.DevicesFrameChatSessions));
|
||||
}
|
||||
|
||||
private void StartRemoteControl(bool viewOnly)
|
||||
private async Task StartRemoteControl(bool viewOnly)
|
||||
{
|
||||
if (!ServiceSessionCache.TryGetConnectionId(Device.ID, out var connectionId))
|
||||
if (!ServiceSessionCache.TryGetConnectionId(Device.ID, out _))
|
||||
{
|
||||
ToastService.ShowToast("Device connection not found", classString: "bg-danger");
|
||||
return;
|
||||
}
|
||||
|
||||
CircuitConnection.RemoteControl(Device.ID, viewOnly);
|
||||
var result = await CircuitConnection.RemoteControl(Device.ID, viewOnly);
|
||||
if (!result.IsSuccess)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var session = result.Value;
|
||||
|
||||
if (!await session.WaitForSessionReady(TimeSpan.FromSeconds(20)))
|
||||
{
|
||||
ToastService.ShowToast("Session failed to start", classString: "bg-danger");
|
||||
return;
|
||||
}
|
||||
|
||||
JsInterop.OpenWindow(
|
||||
$"/RemoteControl/Viewer" +
|
||||
$"?mode=Unattended&sessionId={session.UnattendedSessionId}" +
|
||||
$"&accessKey={session.AccessKey}" +
|
||||
$"&viewonly={viewOnly}",
|
||||
"_blank");
|
||||
}
|
||||
|
||||
private void ToggleIsSelected(ChangeEventArgs args)
|
||||
|
||||
@ -174,16 +174,6 @@ namespace Remotely.Server.Components.Devices
|
||||
AddScriptResult(result);
|
||||
}
|
||||
break;
|
||||
case CircuitEventName.UnattendedSessionReady:
|
||||
{
|
||||
var sessionId = (string)args.Params[0];
|
||||
var accessKey = (string)args.Params[1];
|
||||
var deviceId = (string)args.Params[2];
|
||||
var viewOnly = (bool)args.Params[3];
|
||||
|
||||
JsInterop.OpenWindow($"/RemoteControl/Viewer?mode=Unattended&sessionId={sessionId}&accessKey={accessKey}&viewonly={viewOnly}", "_blank");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using Immense.RemoteControl.Server.Abstractions;
|
||||
using Immense.RemoteControl.Server.Services;
|
||||
using Immense.RemoteControl.Shared;
|
||||
using Immense.RemoteControl.Shared.Helpers;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
@ -40,7 +41,7 @@ namespace Remotely.Server.Hubs
|
||||
Task InvokeCircuitEvent(CircuitEventName eventName, params object[] args);
|
||||
Task ReinstallAgents(string[] deviceIDs);
|
||||
|
||||
Task<bool> RemoteControl(string deviceID, bool viewOnly);
|
||||
Task<Result<RemoteControlSessionEx>> RemoteControl(string deviceID, bool viewOnly);
|
||||
|
||||
Task RemoveDevices(string[] deviceIDs);
|
||||
|
||||
@ -206,7 +207,7 @@ namespace Remotely.Server.Hubs
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task<bool> RemoteControl(string deviceId, bool viewOnly)
|
||||
public async Task<Result<RemoteControlSessionEx>> RemoteControl(string deviceId, bool viewOnly)
|
||||
{
|
||||
if (!_serviceSessionCache.TryGetByDeviceId(deviceId, out var targetDevice))
|
||||
{
|
||||
@ -214,66 +215,65 @@ namespace Remotely.Server.Hubs
|
||||
"The selected device is not online.",
|
||||
"Device is not online.",
|
||||
"bg-warning"));
|
||||
return false;
|
||||
return Result.Fail<RemoteControlSessionEx>("Device is not online.");
|
||||
}
|
||||
|
||||
|
||||
if (_dataService.DoesUserHaveAccessToDevice(deviceId, User))
|
||||
{
|
||||
var sessionCount = _desktopSessionCache.Sessions.Values
|
||||
.OfType<RemoteControlSessionEx>()
|
||||
.Count(x => x.OrganizationId == User.OrganizationID);
|
||||
|
||||
if (sessionCount >= _appConfig.RemoteControlSessionLimit)
|
||||
{
|
||||
MessageReceived?.Invoke(this, new CircuitEvent(CircuitEventName.DisplayMessage,
|
||||
"There are already the maximum amount of active remote control sessions for your organization.",
|
||||
"Max number of concurrent sessions reached.",
|
||||
"bg-warning"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_serviceSessionCache.TryGetConnectionId(targetDevice.ID, out var serviceConnectionId))
|
||||
{
|
||||
MessageReceived?.Invoke(this, new CircuitEvent(CircuitEventName.DisplayMessage,
|
||||
"Service connection not found.",
|
||||
"Service connection not found.",
|
||||
"bg-warning"));
|
||||
return false;
|
||||
}
|
||||
|
||||
var sessionId = Guid.NewGuid().ToString();
|
||||
var accessKey = RandomGenerator.GenerateAccessKey();
|
||||
|
||||
var session = new RemoteControlSessionEx()
|
||||
{
|
||||
UnattendedSessionId = sessionId,
|
||||
UserConnectionId = ConnectionId,
|
||||
ServiceConnectionId = serviceConnectionId,
|
||||
DeviceId = deviceId,
|
||||
ViewOnly = viewOnly,
|
||||
OrganizationId = User.OrganizationID
|
||||
};
|
||||
|
||||
_desktopSessionCache.Sessions.AddOrUpdate(sessionId, session, (k, v) => session);
|
||||
|
||||
var organization = _dataService.GetOrganizationNameByUserName(User.UserName);
|
||||
await _agentHubContext.Clients.Client(serviceConnectionId).SendAsync("RemoteControl",
|
||||
sessionId,
|
||||
accessKey,
|
||||
ConnectionId,
|
||||
User.UserOptions.DisplayName,
|
||||
organization,
|
||||
User.OrganizationID);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (!_dataService.DoesUserHaveAccessToDevice(deviceId, User))
|
||||
{
|
||||
var device = _dataService.GetDevice(targetDevice.ID);
|
||||
_dataService.WriteEvent($"Remote control attempted by unauthorized user. Device ID: {deviceId}. User Name: {User.UserName}.", EventType.Warning, device?.OrganizationID);
|
||||
return false;
|
||||
return Result.Fail<RemoteControlSessionEx>("Unauthorized.");
|
||||
|
||||
}
|
||||
|
||||
var sessionCount = _desktopSessionCache.Sessions
|
||||
.OfType<RemoteControlSessionEx>()
|
||||
.Count(x => x.OrganizationId == User.OrganizationID);
|
||||
|
||||
if (sessionCount >= _appConfig.RemoteControlSessionLimit)
|
||||
{
|
||||
MessageReceived?.Invoke(this, new CircuitEvent(CircuitEventName.DisplayMessage,
|
||||
"There are already the maximum amount of active remote control sessions for your organization.",
|
||||
"Max number of concurrent sessions reached.",
|
||||
"bg-warning"));
|
||||
return Result.Fail<RemoteControlSessionEx>("Max number of concurrent sessions reached.");
|
||||
}
|
||||
|
||||
if (!_serviceSessionCache.TryGetConnectionId(targetDevice.ID, out var serviceConnectionId))
|
||||
{
|
||||
MessageReceived?.Invoke(this, new CircuitEvent(CircuitEventName.DisplayMessage,
|
||||
"Service connection not found.",
|
||||
"Service connection not found.",
|
||||
"bg-warning"));
|
||||
return Result.Fail<RemoteControlSessionEx>("Service connection not found.");
|
||||
}
|
||||
|
||||
var sessionId = Guid.NewGuid();
|
||||
var accessKey = RandomGenerator.GenerateAccessKey();
|
||||
|
||||
var session = new RemoteControlSessionEx()
|
||||
{
|
||||
UnattendedSessionId = sessionId,
|
||||
UserConnectionId = ConnectionId,
|
||||
ServiceConnectionId = serviceConnectionId,
|
||||
DeviceId = deviceId,
|
||||
ViewOnly = viewOnly,
|
||||
OrganizationId = User.OrganizationID
|
||||
};
|
||||
|
||||
_desktopSessionCache.AddOrUpdate($"{sessionId}", session);
|
||||
|
||||
var organization = _dataService.GetOrganizationNameByUserName(User.UserName);
|
||||
await _agentHubContext.Clients.Client(serviceConnectionId).SendAsync("RemoteControl",
|
||||
sessionId,
|
||||
accessKey,
|
||||
ConnectionId,
|
||||
User.UserOptions.DisplayName,
|
||||
organization,
|
||||
User.OrganizationID);
|
||||
|
||||
return Result.Ok(session);
|
||||
}
|
||||
|
||||
public Task RemoveDevices(string[] deviceIDs)
|
||||
|
||||
@ -8,7 +8,6 @@ namespace Remotely.Server.Models
|
||||
public enum CircuitEventName
|
||||
{
|
||||
DisplayMessage,
|
||||
UnattendedSessionReady,
|
||||
ChatReceived,
|
||||
CommandResult,
|
||||
DeviceUpdate,
|
||||
|
||||
@ -34,6 +34,7 @@ using Immense.RemoteControl.Server.Abstractions;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Remotely.Shared.Services;
|
||||
using System;
|
||||
using Immense.RemoteControl.Server.Services;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
var configuration = builder.Configuration;
|
||||
@ -182,7 +183,6 @@ services.AddScoped<ApiAuthorizationFilter>();
|
||||
services.AddScoped<ExpiringTokenFilter>();
|
||||
services.AddHostedService<DbCleanupService>();
|
||||
services.AddHostedService<ScriptScheduler>();
|
||||
services.AddHostedService<DesktopHubSessionCleanup>();
|
||||
services.AddSingleton<IUpgradeService, UpgradeService>();
|
||||
services.AddScoped<IToastService, ToastService>();
|
||||
services.AddScoped<IModalService, ModalService>();
|
||||
@ -199,15 +199,12 @@ services.AddSingleton<IEmbeddedServerDataSearcher, EmbeddedServerDataSearcher>()
|
||||
|
||||
services.AddRemoteControlServer(config =>
|
||||
{
|
||||
config.AddHubEventHandler<HubEventHandlerEx>();
|
||||
config.AddHubEventHandler<HubEventHandler>();
|
||||
config.AddViewerAuthorizer<ViewerAuthorizer>();
|
||||
config.AddViewerHubDataProvider<ViewerHubDataProvider>();
|
||||
config.AddViewerPageDataProvider<ViewerPageDataProvider>();
|
||||
});
|
||||
|
||||
services.RemoveAll<IHubEventHandler>();
|
||||
services.AddScoped<IHubEventHandlerEx, HubEventHandlerEx>();
|
||||
services.AddScoped<IHubEventHandler>(s => s.GetRequiredService<IHubEventHandlerEx>());
|
||||
services.AddSingleton<IServiceHubSessionCache, ServiceHubSessionCache>();
|
||||
|
||||
var app = builder.Build();
|
||||
@ -255,13 +252,11 @@ app.UseCors("TrustedOriginPolicy");
|
||||
|
||||
app.UseRemoteControlServer();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapHub<AgentHub>("/hubs/service");
|
||||
endpoints.MapControllers();
|
||||
endpoints.MapBlazorHub();
|
||||
endpoints.MapFallbackToPage("/_Host");
|
||||
});
|
||||
|
||||
app.MapHub<AgentHub>("/hubs/service");
|
||||
app.MapControllers();
|
||||
app.MapBlazorHub();
|
||||
app.MapFallbackToPage("/_Host");
|
||||
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
|
||||
@ -1,61 +0,0 @@
|
||||
using Immense.RemoteControl.Server.Services;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using System.Linq;
|
||||
using Timer = System.Timers.Timer;
|
||||
using Immense.RemoteControl.Shared.Services;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.Json;
|
||||
using System.Collections.Generic;
|
||||
using Immense.RemoteControl.Server.Models;
|
||||
|
||||
namespace Remotely.Server.Services
|
||||
{
|
||||
public class DesktopHubSessionCleanup : BackgroundService
|
||||
{
|
||||
private readonly IDesktopHubSessionCache _sessionCache;
|
||||
private readonly ISystemTime _systemTime;
|
||||
private readonly ILogger<DesktopHubSessionCleanup> _logger;
|
||||
private Task _cleanupTask;
|
||||
private CancellationToken _stoppingToken;
|
||||
|
||||
public DesktopHubSessionCleanup(
|
||||
IDesktopHubSessionCache sessionCache,
|
||||
ISystemTime systemTime,
|
||||
ILogger<DesktopHubSessionCleanup> logger)
|
||||
{
|
||||
_sessionCache = sessionCache;
|
||||
_systemTime = systemTime;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
protected override Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
_stoppingToken = stoppingToken;
|
||||
_cleanupTask = Task.Run(CleanupSessions, stoppingToken);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task CleanupSessions()
|
||||
{
|
||||
while (!_stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
foreach (var session in _sessionCache.Sessions)
|
||||
{
|
||||
if (session.Value.Mode == RemoteControlMode.Unattended &&
|
||||
!session.Value.ViewerList.Any() &&
|
||||
session.Value.Created < _systemTime.Now.AddMinutes(-1))
|
||||
{
|
||||
_logger.LogWarning("Removing expired session: {session}", JsonSerializer.Serialize(session.Value));
|
||||
_sessionCache.Sessions.Remove(session.Key, out _);
|
||||
}
|
||||
}
|
||||
await Task.Delay(30_000, _stoppingToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -17,25 +17,15 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Remotely.Server.Services.RcImplementations
|
||||
{
|
||||
public interface IHubEventHandlerEx : IHubEventHandler
|
||||
public class HubEventHandler : IHubEventHandler
|
||||
{
|
||||
Task<bool> TryWaitForSession(string sessionId, Func<Task> createSessionFunc);
|
||||
}
|
||||
|
||||
public class HubEventHandlerEx : IHubEventHandlerEx
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, SemaphoreSlim> _sessionWaitHandlers = new();
|
||||
|
||||
private readonly ICircuitManager _circuitManager;
|
||||
private readonly IHubContext<AgentHub> _serviceHub;
|
||||
private readonly ILogger<HubEventHandlerEx> _logger;
|
||||
private readonly ILogger<HubEventHandler> _logger;
|
||||
|
||||
public HubEventHandlerEx(
|
||||
ICircuitManager circuitManager,
|
||||
public HubEventHandler(
|
||||
IHubContext<AgentHub> serviceHub,
|
||||
ILogger<HubEventHandlerEx> logger)
|
||||
ILogger<HubEventHandler> logger)
|
||||
{
|
||||
_circuitManager = circuitManager;
|
||||
_serviceHub = serviceHub;
|
||||
_logger = logger;
|
||||
}
|
||||
@ -108,29 +98,6 @@ namespace Remotely.Server.Services.RcImplementations
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task NotifyUnattendedSessionReady(RemoteControlSession session, string relativeAccessUrl)
|
||||
{
|
||||
if (_sessionWaitHandlers.TryGetValue(session.UnattendedSessionId, out var waitHandle))
|
||||
{
|
||||
waitHandle.Release();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
if (session is not RemoteControlSessionEx ex)
|
||||
{
|
||||
_logger.LogError("Event should have been for RemoteControlSessionEx.");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
return _circuitManager.InvokeOnConnection(
|
||||
ex.UserConnectionId,
|
||||
CircuitEventName.UnattendedSessionReady,
|
||||
session.UnattendedSessionId,
|
||||
session.AccessKey,
|
||||
ex.DeviceId,
|
||||
ex.ViewOnly);
|
||||
}
|
||||
|
||||
public Task RestartScreenCaster(RemoteControlSession session, HashSet<string> viewerList)
|
||||
{
|
||||
|
||||
@ -151,29 +118,5 @@ namespace Remotely.Server.Services.RcImplementations
|
||||
ex.OrganizationName,
|
||||
ex.OrganizationId);
|
||||
}
|
||||
|
||||
public async Task<bool> TryWaitForSession(string sessionId, Func<Task> createSessionFunc)
|
||||
{
|
||||
try
|
||||
{
|
||||
var waitHandle = _sessionWaitHandlers.AddOrUpdate(sessionId, new SemaphoreSlim(0, 1), (k, v) =>
|
||||
{
|
||||
v.Release();
|
||||
return new SemaphoreSlim(0, 1);
|
||||
});
|
||||
|
||||
await createSessionFunc();
|
||||
|
||||
return waitHandle.Wait(TimeSpan.FromSeconds(30));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_sessionWaitHandlers.TryRemove(sessionId, out var result))
|
||||
{
|
||||
result.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,31 +12,37 @@ namespace Remotely.Server.Services.RcImplementations
|
||||
{
|
||||
public class ViewerPageDataProvider : IViewerPageDataProvider
|
||||
{
|
||||
private readonly IDataService _dataService;
|
||||
private readonly IApplicationConfig _appConfig;
|
||||
|
||||
private readonly IDataService _dataService;
|
||||
public ViewerPageDataProvider(IDataService dataService, IApplicationConfig appConfig)
|
||||
{
|
||||
_dataService = dataService;
|
||||
_appConfig = appConfig;
|
||||
}
|
||||
|
||||
public Task<string> GetUserDisplayName(PageModel pageModel)
|
||||
|
||||
public Task<string> GetFaviconUrl(ViewerModel viewerModel)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(pageModel?.User?.Identity?.Name))
|
||||
{
|
||||
return Task.FromResult(string.Empty);
|
||||
}
|
||||
return Task.FromResult("/_content/Immense.RemoteControl.Server/favicon.ico");
|
||||
}
|
||||
|
||||
var user = _dataService.GetUserByNameWithOrg(pageModel.User.Identity.Name);
|
||||
public Task<string> GetPageDescription(ViewerModel viewerModel)
|
||||
{
|
||||
return Task.FromResult("Open-source remote support tools.");
|
||||
}
|
||||
|
||||
if (user is null)
|
||||
{
|
||||
return Task.FromResult(string.Empty);
|
||||
}
|
||||
public Task<string> GetPageTitle(PageModel pageModel)
|
||||
{
|
||||
return Task.FromResult("Remotely Remote Control");
|
||||
}
|
||||
|
||||
var displayName = user.UserOptions?.DisplayName ?? user.UserName ?? string.Empty;
|
||||
return Task.FromResult(displayName);
|
||||
public Task<string> GetProductName(PageModel pageModel)
|
||||
{
|
||||
return Task.FromResult("Remotely");
|
||||
}
|
||||
|
||||
public Task<string> GetProductSubtitle(PageModel pageModel)
|
||||
{
|
||||
return Task.FromResult("Remote Control");
|
||||
}
|
||||
|
||||
public Task<ViewerPageTheme> GetTheme(PageModel pageModel)
|
||||
@ -63,24 +69,22 @@ namespace Remotely.Server.Services.RcImplementations
|
||||
return Task.FromResult(appTheme);
|
||||
}
|
||||
|
||||
public Task<string> GetPageTitle(PageModel pageModel)
|
||||
public Task<string> GetUserDisplayName(PageModel pageModel)
|
||||
{
|
||||
return Task.FromResult("Remotely Remote Control");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(pageModel?.User?.Identity?.Name))
|
||||
{
|
||||
return Task.FromResult(string.Empty);
|
||||
}
|
||||
|
||||
public Task<string> GetProductName(PageModel pageModel)
|
||||
{
|
||||
return Task.FromResult("Remotely");
|
||||
}
|
||||
var user = _dataService.GetUserByNameWithOrg(pageModel.User.Identity.Name);
|
||||
|
||||
public Task<string> GetProductSubtitle(PageModel pageModel)
|
||||
{
|
||||
return Task.FromResult("Remote Control");
|
||||
}
|
||||
if (user is null)
|
||||
{
|
||||
return Task.FromResult(string.Empty);
|
||||
}
|
||||
|
||||
public Task<string> GetPageDescription(ViewerModel viewerModel)
|
||||
{
|
||||
return Task.FromResult("Open-source remote support tools.");
|
||||
var displayName = user.UserOptions?.DisplayName ?? user.UserName ?? string.Empty;
|
||||
return Task.FromResult(displayName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,10 @@
|
||||
<RootNamespace>Remotely.Tests.LoadTester</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Moq" Version="4.18.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Agent\Agent.csproj" />
|
||||
<ProjectReference Include="..\..\Desktop.Win\Desktop.Win.csproj" />
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using Castle.Core.Logging;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Remotely.Agent.Services;
|
||||
using Remotely.Agent.Services.Windows;
|
||||
using System;
|
||||
@ -15,11 +18,17 @@ namespace Remotely.Tests.LoadTester
|
||||
private static int _agentCount;
|
||||
private static string _organizationId;
|
||||
private static string _serverurl;
|
||||
private static Mock<ICpuUtilizationSampler> _cpuSampler;
|
||||
private static Mock<ILogger<DeviceInfoGeneratorWin>> _logger;
|
||||
private static DeviceInfoGeneratorWin _deviceInfo;
|
||||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
_deviceInfo = new DeviceInfoGeneratorWin();
|
||||
_cpuSampler = new Mock<ICpuUtilizationSampler>();
|
||||
_cpuSampler.Setup(x => x.CurrentUtilization).Returns(0);
|
||||
_logger = new Mock<ILogger<DeviceInfoGeneratorWin>>();
|
||||
|
||||
_deviceInfo = new DeviceInfoGeneratorWin(_cpuSampler.Object, _logger.Object);
|
||||
ConnectAgents();
|
||||
|
||||
Console.Write("Press Enter to exit...");
|
||||
|
||||
@ -92,25 +92,25 @@ if ([string]::IsNullOrWhiteSpace($MSBuildPath) -or !(Test-Path -Path $MSBuildPat
|
||||
|
||||
|
||||
# Clear publish folders.
|
||||
if ((Test-Path -Path "$Root\Agent\bin\Release\.net7.0\win10-x64\publish") -eq $true) {
|
||||
Get-ChildItem -Path "$Root\Agent\bin\Release\.net7.0\win10-x64\publish" | Remove-Item -Force -Recurse
|
||||
if ((Test-Path -Path "$Root\Agent\bin\Release\net7.0\win10-x64\publish") -eq $true) {
|
||||
Get-ChildItem -Path "$Root\Agent\bin\Release\net7.0\win10-x64\publish" | Remove-Item -Force -Recurse
|
||||
}
|
||||
if ((Test-Path -Path "$Root\Agent\bin\Release\.net7.0\win10-x86\publish" ) -eq $true) {
|
||||
Get-ChildItem -Path "$Root\Agent\bin\Release\.net7.0\win10-x86\publish" | Remove-Item -Force -Recurse
|
||||
if ((Test-Path -Path "$Root\Agent\bin\Release\net7.0\win10-x86\publish" ) -eq $true) {
|
||||
Get-ChildItem -Path "$Root\Agent\bin\Release\net7.0\win10-x86\publish" | Remove-Item -Force -Recurse
|
||||
}
|
||||
if ((Test-Path -Path "$Root\Agent\bin\Release\.net7.0\linux-x64\publish") -eq $true) {
|
||||
Get-ChildItem -Path "$Root\Agent\bin\Release\.net7.0\linux-x64\publish" | Remove-Item -Force -Recurse
|
||||
if ((Test-Path -Path "$Root\Agent\bin\Release\net7.0\linux-x64\publish") -eq $true) {
|
||||
Get-ChildItem -Path "$Root\Agent\bin\Release\net7.0\linux-x64\publish" | Remove-Item -Force -Recurse
|
||||
}
|
||||
|
||||
|
||||
# Publish Core clients.
|
||||
dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion --runtime win10-x64 --self-contained --configuration Release --output "$Root\Agent\bin\Release\.net7.0\win10-x64\publish" "$Root\Agent"
|
||||
dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion --runtime linux-x64 --self-contained --configuration Release --output "$Root\Agent\bin\Release\.net7.0\linux-x64\publish" "$Root\Agent"
|
||||
dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion --runtime win10-x86 --self-contained --configuration Release --output "$Root\Agent\bin\Release\.net7.0\win10-x86\publish" "$Root\Agent"
|
||||
dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion --runtime win10-x64 --self-contained --configuration Release --output "$Root\Agent\bin\Release\net7.0\win10-x64\publish" "$Root\Agent"
|
||||
dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion --runtime linux-x64 --self-contained --configuration Release --output "$Root\Agent\bin\Release\net7.0\linux-x64\publish" "$Root\Agent"
|
||||
dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion --runtime win10-x86 --self-contained --configuration Release --output "$Root\Agent\bin\Release\net7.0\win10-x86\publish" "$Root\Agent"
|
||||
|
||||
New-Item -Path "$Root\Agent\bin\Release\.net7.0\win10-x64\publish\Desktop\" -ItemType Directory -Force
|
||||
New-Item -Path "$Root\Agent\bin\Release\.net7.0\win10-x86\publish\Desktop\" -ItemType Directory -Force
|
||||
New-Item -Path "$Root\Agent\bin\Release\.net7.0\linux-x64\publish\Desktop\" -ItemType Directory -Force
|
||||
New-Item -Path "$Root\Agent\bin\Release\net7.0\win10-x64\publish\Desktop\" -ItemType Directory -Force
|
||||
New-Item -Path "$Root\Agent\bin\Release\net7.0\win10-x86\publish\Desktop\" -ItemType Directory -Force
|
||||
New-Item -Path "$Root\Agent\bin\Release\net7.0\linux-x64\publish\Desktop\" -ItemType Directory -Force
|
||||
|
||||
|
||||
# Publish Linux ScreenCaster
|
||||
@ -155,7 +155,7 @@ if ($SignAssemblies) {
|
||||
}
|
||||
|
||||
# Compress Core clients.
|
||||
$PublishDir = "$Root\Agent\bin\Release\.net7.0\win10-x64\publish"
|
||||
$PublishDir = "$Root\Agent\bin\Release\net7.0\win10-x64\publish"
|
||||
Compress-Archive -Path "$PublishDir\*" -DestinationPath "$PublishDir\Remotely-Win10-x64.zip" -Force
|
||||
while ((Test-Path -Path "$PublishDir\Remotely-Win10-x64.zip") -eq $false){
|
||||
Write-Host "Waiting for archive to finish: $PublishDir\Remotely-Win10-x64.zip"
|
||||
@ -163,7 +163,7 @@ while ((Test-Path -Path "$PublishDir\Remotely-Win10-x64.zip") -eq $false){
|
||||
}
|
||||
Move-Item -Path "$PublishDir\Remotely-Win10-x64.zip" -Destination "$Root\Server\wwwroot\Content\Remotely-Win10-x64.zip" -Force
|
||||
|
||||
$PublishDir = "$Root\Agent\bin\Release\.net7.0\win10-x86\publish"
|
||||
$PublishDir = "$Root\Agent\bin\Release\net7.0\win10-x86\publish"
|
||||
Compress-Archive -Path "$PublishDir\*" -DestinationPath "$PublishDir\Remotely-Win10-x86.zip" -Force
|
||||
while ((Test-Path -Path "$PublishDir\Remotely-Win10-x86.zip") -eq $false){
|
||||
Write-Host "Waiting for archive to finish: $PublishDir\Remotely-Win10-x86.zip"
|
||||
@ -171,7 +171,7 @@ while ((Test-Path -Path "$PublishDir\Remotely-Win10-x86.zip") -eq $false){
|
||||
}
|
||||
Move-Item -Path "$PublishDir\Remotely-Win10-x86.zip" -Destination "$Root\Server\wwwroot\Content\Remotely-Win10-x86.zip" -Force
|
||||
|
||||
$PublishDir = "$Root\Agent\bin\Release\.net7.0\linux-x64\publish"
|
||||
$PublishDir = "$Root\Agent\bin\Release\net7.0\linux-x64\publish"
|
||||
Compress-Archive -Path "$PublishDir\*" -DestinationPath "$PublishDir\Remotely-Linux.zip" -Force
|
||||
while ((Test-Path -Path "$PublishDir\Remotely-Linux.zip") -eq $false){
|
||||
Write-Host "Waiting for archive to finish: $PublishDir\Remotely-Win10-x86.zip"
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit c2f38702bbba6db17b73b5578b0173e1dd81ac39
|
||||
Subproject commit 39d4f853eaa2a87590fb3a56e35db244f6eae08e
|
||||
Loading…
Reference in New Issue
Block a user