Skip to content

Commit

Permalink
Merge pull request #348 from lucent-sea/mac-support
Browse files Browse the repository at this point in the history
Mac support (agent only)
  • Loading branch information
bitbound authored May 8, 2021
2 parents a606372 + fa48849 commit 0f828b5
Show file tree
Hide file tree
Showing 80 changed files with 960 additions and 313 deletions.
50 changes: 49 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,51 @@ on:

jobs:

build:
build-mac:

runs-on: macos-10.15

steps:
- name: Checkout
uses: actions/checkout@v2

- name: Install .NET Core
uses: actions/[email protected]

- name: Set current version
shell: pwsh
run: |
$VersionString = git show -s --format=%ci
$VersionDate = [DateTimeOffset]::Parse($VersionString)
$Year = $VersionDate.Year.ToString()
$Month = $VersionDate.Month.ToString().PadLeft(2, "0")
$Day = $VersionDate.Day.ToString().PadLeft(2, "0")
$Hour = $VersionDate.Hour.ToString().PadLeft(2, "0")
$Minute = $VersionDate.Minute.ToString().PadLeft(2, "0")
$CurrentVersion = "$Year.$Month.$Day.$Hour$Minute"
echo "CurrentVersion=$CurrentVersion" >> $GITHUB_ENV
Write-Host "Setting current version to $CurrentVersion."
- name: Set current version
shell: pwsh
run: |
dotnet publish /p:Version=$env:CurrentVersion /p:FileVersion=$env:CurrentVersion --runtime osx-x64 --configuration Release --output "./Agent/bin/publish" ".\Agent"
Compress-Archive -Path "./Agent/bin/publish/*" -DestinationPath "./Agent/bin/Remotely-MacOS-x64.zip" -Force
- name: Upload build artifact
uses: actions/upload-artifact@v2
with:
path: ./Agent/bin/Remotely-MacOS-x64.zip
name: Mac-Agent-x64

build-windows:

runs-on: windows-latest # For a list of available runner types, refer to
# https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on
needs: build-mac

env:
Solution_Name: Remotely.sln
Expand All @@ -46,6 +87,13 @@ jobs:
ServerUrl: ${{ github.event.inputs.serverUrl }}

steps:

- uses: actions/download-artifact@v2
with:
name: Mac-Agent-x64
path: ./Server/wwwroot/Content/Remotely-MacOS-x64.zip


- name: Checkout
uses: actions/checkout@v2
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -291,3 +291,4 @@ Server/wwwroot/Content/Win-x86/*
Server/.config/dotnet-tools.json
/Server/Properties/ServiceDependencies/*
Server.Installer/Properties/launchSettings.json
.DS_Store
4 changes: 0 additions & 4 deletions Agent/Agent.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,4 @@
</ItemGroup>


<ItemGroup>
<Compile Update="Services\WindowsService.cs" />
</ItemGroup>

</Project>
5 changes: 3 additions & 2 deletions Agent/Interfaces/IUpdater.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;

namespace Remotely.Agent.Interfaces
{
public interface IUpdater
public interface IUpdater : IDisposable
{
Task BeginChecking();
Task CheckForUpdates();
Expand Down
7 changes: 6 additions & 1 deletion Agent/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Remotely.Agent.Services;
using Remotely.Shared.Enums;
using Remotely.Shared.Utilities;
using Remotely.Shared.Services;
using System;
using System.Diagnostics;
using System.IO;
Expand Down Expand Up @@ -52,6 +53,8 @@ private static void BuildServices()
serviceCollection.AddScoped<ConfigService>();
serviceCollection.AddScoped<Uninstaller>();
serviceCollection.AddScoped<ScriptExecutor>();
serviceCollection.AddScoped<IProcessInvoker, ProcessInvoker>();
serviceCollection.AddScoped<IWebClientEx, WebClientEx>();

if (EnvironmentHelper.IsWindows)
{
Expand All @@ -67,7 +70,9 @@ private static void BuildServices()
}
else if (EnvironmentHelper.IsMac)
{
// TODO: Mac.
serviceCollection.AddScoped<IAppLauncher, AppLauncherMac>();
serviceCollection.AddSingleton<IUpdater, UpdaterMac>();
serviceCollection.AddSingleton<IDeviceInformationService, DeviceInformationServiceMac>();
}
else
{
Expand Down
29 changes: 16 additions & 13 deletions Agent/Services/AppLauncherLinux.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.SignalR.Client;
using Remotely.Agent.Interfaces;
using Remotely.Shared.Models;
using Remotely.Shared.Services;
using Remotely.Shared.Utilities;
using System;
using System.Collections.Generic;
Expand All @@ -15,13 +16,15 @@ namespace Remotely.Agent.Services
public class AppLauncherLinux : IAppLauncher
{
private readonly string _rcBinaryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Desktop", EnvironmentHelper.DesktopExecutableFileName);
private readonly IProcessInvoker _processInvoker;
private readonly ConnectionInfo _connectionInfo;

public AppLauncherLinux(ConfigService configService)
public AppLauncherLinux(ConfigService configService, IProcessInvoker processInvoker)
{
ConnectionInfo = configService.GetConnectionInfo();
_processInvoker = processInvoker;
_connectionInfo = configService.GetConnectionInfo();
}

private ConnectionInfo ConnectionInfo { get; }

public async Task<int> LaunchChatService(string orgName, string requesterID, HubConnection hubConnection)
{
Expand All @@ -43,8 +46,8 @@ await hubConnection.SendAsync("DisplayMessage",
$"-mode Chat " +
$"-requester \"{requesterID}\" " +
$"-organization \"{orgName}\" " +
$"-host \"{ConnectionInfo.Host}\" " +
$"-orgid \"{ConnectionInfo.OrganizationID}\"";
$"-host \"{_connectionInfo.Host}\" " +
$"-orgid \"{_connectionInfo.OrganizationID}\"";
return StartLinuxDesktopApp(args);
}
catch (Exception ex)
Expand Down Expand Up @@ -76,9 +79,9 @@ await hubConnection.SendAsync("DisplayMessage",
$"-mode Unattended " +
$"-requester \"{requesterID}\" " +
$"-serviceid \"{serviceID}\" " +
$"-deviceid {ConnectionInfo.DeviceID} " +
$"-host \"{ConnectionInfo.Host}\" " +
$"-orgid \"{ConnectionInfo.OrganizationID}\"";
$"-deviceid {_connectionInfo.DeviceID} " +
$"-host \"{_connectionInfo.Host}\" " +
$"-orgid \"{_connectionInfo.OrganizationID}\"";
StartLinuxDesktopApp(args);
}
catch (Exception ex)
Expand All @@ -96,9 +99,9 @@ public async Task RestartScreenCaster(List<string> viewerIDs, string serviceID,
$"-mode Unattended " +
$"-requester \"{requesterID}\" " +
$"-serviceid \"{serviceID}\" " +
$"-deviceid {ConnectionInfo.DeviceID} " +
$"-host \"{ConnectionInfo.Host}\" " +
$"-orgid \"{ConnectionInfo.OrganizationID}\" " +
$"-deviceid {_connectionInfo.DeviceID} " +
$"-host \"{_connectionInfo.Host}\" " +
$"-orgid \"{_connectionInfo.OrganizationID}\" " +
$"-relaunch true " +
$"-viewers {string.Join(",", viewerIDs)}";
StartLinuxDesktopApp(args);
Expand All @@ -116,7 +119,7 @@ private int StartLinuxDesktopApp(string args)
var xauthority = GetXorgAuth();

var display = ":0";
var whoString = EnvironmentHelper.StartProcessWithResults("who", "")?.Trim();
var whoString = _processInvoker.InvokeProcessOutput("who", "")?.Trim();
var username = "";

if (!string.IsNullOrWhiteSpace(whoString))
Expand Down Expand Up @@ -155,7 +158,7 @@ private string GetXorgAuth()
{
try
{
var processes = EnvironmentHelper.StartProcessWithResults("ps", "-eaf")?.Split(Environment.NewLine);
var processes = _processInvoker.InvokeProcessOutput("ps", "-eaf")?.Split(Environment.NewLine);
if (processes?.Length > 0)
{
var xorgLine = processes.FirstOrDefault(x => x.Contains("xorg", StringComparison.OrdinalIgnoreCase));
Expand Down
26 changes: 26 additions & 0 deletions Agent/Services/AppLauncherMac.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR.Client;
using Remotely.Agent.Interfaces;

namespace Remotely.Agent.Services
{
public class AppLauncherMac : IAppLauncher
{
public async Task<int> LaunchChatService(string orgName, string requesterID, HubConnection hubConnection)
{
await hubConnection.SendAsync("DisplayMessage", "Feature under development.", "Feature is under development.", "bg-warning", requesterID);
return 0;
}

public async Task LaunchRemoteControl(int targetSessionId, string requesterID, string serviceID, HubConnection hubConnection)
{
await hubConnection.SendAsync("DisplayMessage", "Feature under development.", "Feature is under development.", "bg-warning", requesterID);
}

public async Task RestartScreenCaster(List<string> viewerIDs, string serviceID, string requesterID, HubConnection hubConnection, int targetSessionID = -1)
{
await hubConnection.SendAsync("DisplayMessage", "Feature under development.", "Feature is under development.", "bg-warning", requesterID);
}
}
}
2 changes: 1 addition & 1 deletion Agent/Services/ConfigService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public ConnectionInfo GetConnectionInfo()
return new ConnectionInfo()
{
DeviceID = _debugGuid,
Host = "https://localhost:5001",
Host = "http://localhost:5000",
OrganizationID = orgID
};
}
Expand Down
1 change: 1 addition & 0 deletions Agent/Services/DeviceInformationServiceBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Remotely.Shared.Models;
using Remotely.Shared.Services;
using Remotely.Shared.Utilities;
using System;
using System.Collections.Generic;
Expand Down
11 changes: 9 additions & 2 deletions Agent/Services/DeviceInformationServiceLinux.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Remotely.Agent.Interfaces;
using Remotely.Shared.Models;
using Remotely.Shared.Services;
using Remotely.Shared.Utilities;
using System;
using System.Collections.Generic;
Expand All @@ -11,6 +12,12 @@ namespace Remotely.Agent.Services
{
public class DeviceInformationServiceLinux : DeviceInformationServiceBase, IDeviceInformationService
{
private readonly IProcessInvoker _processInvoker;

public DeviceInformationServiceLinux(IProcessInvoker processInvoker)
{
_processInvoker = processInvoker;
}
public async Task<Device> CreateDevice(string deviceId, string orgId)
{
var device = GetDeviceBase(deviceId, orgId);
Expand Down Expand Up @@ -40,15 +47,15 @@ public async Task<Device> CreateDevice(string deviceId, string orgId)

private string GetCurrentUser()
{
var users = EnvironmentHelper.StartProcessWithResults("users", "");
var users = _processInvoker.InvokeProcessOutput("users", "");
return users?.Split()?.FirstOrDefault()?.Trim();
}

public (double usedGB, double totalGB) GetMemoryInGB()
{
try
{
var results = EnvironmentHelper.StartProcessWithResults("cat", "/proc/meminfo");
var results = _processInvoker.InvokeProcessOutput("cat", "/proc/meminfo");
var resultsArr = results.Split("\n".ToCharArray());
var freeKB = resultsArr
.FirstOrDefault(x => x.Trim().StartsWith("MemAvailable"))
Expand Down
115 changes: 115 additions & 0 deletions Agent/Services/DeviceInformationServiceMac.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using Remotely.Agent.Interfaces;
using Remotely.Shared.Models;
using Remotely.Shared.Services;
using Remotely.Shared.Utilities;
using Remotely.Shared.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Remotely.Agent.Services
{
public class DeviceInformationServiceMac : DeviceInformationServiceBase, IDeviceInformationService
{
private readonly IProcessInvoker _processInvoker;

public DeviceInformationServiceMac(IProcessInvoker processInvoker)
{
_processInvoker = processInvoker;
}
public async Task<Device> CreateDevice(string deviceId, string orgId)
{
var device = GetDeviceBase(deviceId, orgId);

try
{

var (usedStorage, totalStorage) = GetSystemDriveInfo();
var (usedMemory, totalMemory) = GetMemoryInGB();

device.CurrentUser = Environment.UserName;
device.Drives = GetAllDrives();
device.UsedStorage = usedStorage;
device.TotalStorage = totalStorage;
device.UsedMemory = usedMemory;
device.TotalMemory = totalMemory;
device.CpuUtilization = await GetCpuUtilization();
device.AgentVersion = GetAgentVersion();
}
catch (Exception ex)
{
Logger.Write(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
{
double totalGB = default;

var totalMemoryString = _processInvoker.InvokeProcessOutput("zsh", "-c \"sysctl -n hw.memsize\"");
if (double.TryParse(totalMemoryString, out var totalMemory))
{
totalGB = (double)Math.Round(totalMemory / 1024 / 1024 / 1024, 2);
}


double usedGB = default;

var memPercentStrings = _processInvoker.InvokeProcessOutput("zsh", $"-c \"ps -A -o %mem\"");

double usedMemPercent = 0;
memPercentStrings
.Split(Environment.NewLine)
.ToList()
.ForEach(x => {
if (double.TryParse(x, out var result))
{
usedMemPercent += result;
}
});

usedMemPercent = usedMemPercent / 4 / 100;
usedGB = usedMemPercent * totalGB;

return (usedGB,totalGB);
}
catch
{
return (0, 0);
}
}
}
}
Loading

0 comments on commit 0f828b5

Please sign in to comment.