diff --git a/src/AppCommon/FileTime.App.Core/Configuration/MainConfiguration.cs b/src/AppCommon/FileTime.App.Core/Configuration/MainConfiguration.cs
index 6ff16d9..759fd31 100644
--- a/src/AppCommon/FileTime.App.Core/Configuration/MainConfiguration.cs
+++ b/src/AppCommon/FileTime.App.Core/Configuration/MainConfiguration.cs
@@ -13,13 +13,7 @@ public class MainConfiguration
static MainConfiguration()
{
- var serverFileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
- ? "FileTime.Server.exe"
- : "FileTime.Server";
- Configuration = new()
- {
- {AdminElevationConfiguration.SectionName + ":" + nameof(AdminElevationConfiguration.ServerExecutablePath), serverFileName},
- };
+ Configuration = new();
PopulateDefaultEditorPrograms(Configuration);
PopulateDefaultKeyBindings(Configuration, DefaultKeybindings.Value,
diff --git a/src/ConsoleApp/FileTime.ConsoleUI/FileTime.ConsoleUI.csproj b/src/ConsoleApp/FileTime.ConsoleUI/FileTime.ConsoleUI.csproj
index 85b9c05..307f292 100644
--- a/src/ConsoleApp/FileTime.ConsoleUI/FileTime.ConsoleUI.csproj
+++ b/src/ConsoleApp/FileTime.ConsoleUI/FileTime.ConsoleUI.csproj
@@ -18,6 +18,7 @@
+
diff --git a/src/ConsoleApp/FileTime.ConsoleUI/Program.cs b/src/ConsoleApp/FileTime.ConsoleUI/Program.cs
index a936bba..bd1337f 100644
--- a/src/ConsoleApp/FileTime.ConsoleUI/Program.cs
+++ b/src/ConsoleApp/FileTime.ConsoleUI/Program.cs
@@ -15,6 +15,12 @@ using TerminalUI.ConsoleDrivers;
using ITheme = FileTime.ConsoleUI.App.Styling.ITheme;
using Version = FileTime.ConsoleUI.InfoProviders.Version;
+if(args.Length > 0 && args[0] == "--server")
+{
+ FileTime.Server.Program.Main(args.Skip(1).ToArray());
+ return;
+}
+
Console.OutputEncoding = System.Text.Encoding.UTF8;
IConsoleDriver? driver = null;
diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/FileTime.GuiApp.csproj b/src/GuiApp/Avalonia/FileTime.GuiApp/FileTime.GuiApp.csproj
index d38c35d..c2afc2a 100644
--- a/src/GuiApp/Avalonia/FileTime.GuiApp/FileTime.GuiApp.csproj
+++ b/src/GuiApp/Avalonia/FileTime.GuiApp/FileTime.GuiApp.csproj
@@ -47,6 +47,7 @@
+
diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Program.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Program.cs
index 2e523fa..2e57bb4 100644
--- a/src/GuiApp/Avalonia/FileTime.GuiApp/Program.cs
+++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Program.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
+using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;
@@ -56,6 +57,12 @@ public static class Program
[STAThread]
public static async Task Main(string[] args)
{
+ if(args.Length > 0 && args[0] == "--server")
+ {
+ Server.Program.Main(args.Skip(1).ToArray());
+ return;
+ }
+
#if DEBUG
(AppDataRoot, EnvironmentName) = Init.InitDevelopment();
#endif
diff --git a/src/Providers/FileTime.Providers.LocalAdmin.Abstractions/AdminElevationConfiguration.cs b/src/Providers/FileTime.Providers.LocalAdmin.Abstractions/AdminElevationConfiguration.cs
index b30a069..5063d20 100644
--- a/src/Providers/FileTime.Providers.LocalAdmin.Abstractions/AdminElevationConfiguration.cs
+++ b/src/Providers/FileTime.Providers.LocalAdmin.Abstractions/AdminElevationConfiguration.cs
@@ -3,7 +3,7 @@
public class AdminElevationConfiguration
{
public const string SectionName = "AdminElevation";
- public string ServerExecutablePath { get; set; }
+ public string? ServerExecutablePath { get; set; }
public string LinuxElevationTool { get; set; }
public int? ServerPort { get; set; }
public bool? StartProcess { get; set; }
diff --git a/src/Providers/FileTime.Providers.LocalAdmin/AdminElevationManager.cs b/src/Providers/FileTime.Providers.LocalAdmin/AdminElevationManager.cs
index 8a03fad..4321ae8 100644
--- a/src/Providers/FileTime.Providers.LocalAdmin/AdminElevationManager.cs
+++ b/src/Providers/FileTime.Providers.LocalAdmin/AdminElevationManager.cs
@@ -16,6 +16,7 @@ namespace FileTime.Providers.LocalAdmin;
public class AdminElevationManager : IAdminElevationManager, INotifyPropertyChanged, IExitHandler
{
private const string AdminContentProviderName = "localAdminRemote";
+
private class ConnectionInfo
{
public string? SignalRBaseUrl { get; init; }
@@ -60,8 +61,6 @@ public class AdminElevationManager : IAdminElevationManager, INotifyPropertyChan
public async Task CreateAdminInstanceIfNecessaryAsync(string? confirmationMessage = null)
{
- ArgumentNullException.ThrowIfNull(_configuration.CurrentValue.ServerExecutablePath, "ServerExecutablePath");
-
await _lock.WaitAsync();
try
{
@@ -74,11 +73,11 @@ public class AdminElevationManager : IAdminElevationManager, INotifyPropertyChan
var port = _configuration.CurrentValue.ServerPort;
_logger.LogTrace("Admin server port is {Port}", port is null ? "" : $"{port}");
if (StartProcess || port is null)
- {
+ {
var portFileName = Path.GetTempFileName();
File.Delete(portFileName);
-
- var process = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
+
+ var process = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? CreateWindowsAdminProcess(portFileName)
: CreateLinuxAdminProcess(portFileName);
process.Exited += ProcessExitHandler;
@@ -131,40 +130,74 @@ public class AdminElevationManager : IAdminElevationManager, INotifyPropertyChan
}
}
- private Process CreateWindowsAdminProcess(string portFileName)
- => new()
+ private Process CreateWindowsAdminProcess(string portFileName)
+ {
+ var (fileName, arguments) = GetServerPathAndArgs(portFileName);
+ var process = new Process
{
StartInfo = new()
{
- FileName = _configuration.CurrentValue.ServerExecutablePath,
- ArgumentList =
- {
- "--PortWriter:FileName",
- portFileName
- },
+ FileName = fileName,
UseShellExecute = true,
Verb = "runas"
},
EnableRaisingEvents = true
};
+ foreach (var argument in arguments)
+ {
+ process.StartInfo.ArgumentList.Add(argument);
+ }
+
+ return process;
+ }
+
private Process CreateLinuxAdminProcess(string portFileName)
{
- return new Process
+ var (fileName, arguments) = GetServerPathAndArgs(portFileName);
+
+ arguments = arguments.Prepend(fileName);
+
+ var process = new Process
{
StartInfo = new()
{
FileName = _configuration.CurrentValue.LinuxElevationTool,
- ArgumentList =
- {
- _configuration.CurrentValue.ServerExecutablePath,
- "--PortWriter:FileName",
- portFileName
- },
CreateNoWindow = true
},
EnableRaisingEvents = true
};
+
+ foreach (var argument in arguments)
+ {
+ process.StartInfo.ArgumentList.Add(argument);
+ }
+
+ return process;
+ }
+
+ private (string fileName, IEnumerable arguments) GetServerPathAndArgs(string portFileName)
+ {
+ var selfStart = _configuration.CurrentValue.ServerExecutablePath is null;
+
+ var fileName = selfStart
+ ? Process.GetCurrentProcess().MainModule?.FileName
+ : _configuration.CurrentValue.ServerExecutablePath;
+
+ if(fileName is null) throw new Exception("Could not get server executable path");
+
+ IEnumerable arguments = new[]
+ {
+ "--PortWriter:FileName",
+ portFileName
+ };
+
+ if (selfStart)
+ {
+ arguments = arguments.Prepend("--server");
+ }
+
+ return (fileName, arguments);
}
//Note: this does not have to return a task
@@ -172,7 +205,7 @@ public class AdminElevationManager : IAdminElevationManager, INotifyPropertyChan
{
try
{
- if (_remoteContentProvider != null) return Task.FromResult((IRemoteContentProvider)_remoteContentProvider);
+ if (_remoteContentProvider != null) return Task.FromResult((IRemoteContentProvider) _remoteContentProvider);
ArgumentNullException.ThrowIfNull(_connectionInfo);
//TODO: use other connections too (if there will be any)
@@ -186,7 +219,7 @@ public class AdminElevationManager : IAdminElevationManager, INotifyPropertyChan
AdminContentProviderName
);
- return Task.FromResult((IRemoteContentProvider)_remoteContentProvider);
+ return Task.FromResult((IRemoteContentProvider) _remoteContentProvider);
}
catch (Exception ex)
{
diff --git a/src/Server/FileTime.Server/Program.cs b/src/Server/FileTime.Server/Program.cs
index c72c2f4..85f0bfa 100644
--- a/src/Server/FileTime.Server/Program.cs
+++ b/src/Server/FileTime.Server/Program.cs
@@ -2,83 +2,89 @@
using Autofac.Extensions.DependencyInjection;
using FileTime.App.DependencyInjection;
using FileTime.Providers.Local;
-using FileTime.Server;
using FileTime.Server.App;
using FileTime.Server.Common;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
+namespace FileTime.Server;
-var applicationCancellation = new CancellationTokenSource();
-var configurationRoot = CreateConfiguration();
+public static class Program
+{
+ public static void Main(string[] args)
+ {
+ var applicationCancellation = new CancellationTokenSource();
+ var configurationRoot = CreateConfiguration();
-Log.Logger = new LoggerConfiguration()
+ Log.Logger = new LoggerConfiguration()
#if DEBUG
- .MinimumLevel.Verbose()
- .ReadFrom.Configuration(configurationRoot)
+ .MinimumLevel.Verbose()
+ .ReadFrom.Configuration(configurationRoot)
#else
.MinimumLevel.Information()
#endif
- .WriteTo.Console()
- .CreateLogger();
+ .WriteTo.Console()
+ .CreateLogger();
-var rootContainer = CreateRootDiContainer(configurationRoot);
+ var rootContainer = CreateRootDiContainer(configurationRoot);
-var handlerParameters = new ConnectionHandlerParameters(
- args,
- rootContainer,
- configurationRoot,
- applicationCancellation.Token
-);
+ var handlerParameters = new ConnectionHandlerParameters(
+ args,
+ rootContainer,
+ configurationRoot,
+ applicationCancellation.Token
+ );
-var webThread = CreateStartup(FileTime.Server.Web.Program.Start);
-webThread.Start();
+ var webThread = CreateStartup(FileTime.Server.Web.Program.Start);
+ webThread.Start();
-Thread CreateStartup(Func startup)
-{
- var thread = new Thread(() => { HandleStartup(() => startup(handlerParameters).Wait()); });
- return thread;
-}
+ Thread CreateStartup(Func startup)
+ {
+ var thread = new Thread(() => { HandleStartup(() => startup(handlerParameters).Wait()); });
+ return thread;
+ }
-void HandleStartup(Action action)
-{
- try
- {
- action();
- }
- catch (Exception e)
- {
- Console.WriteLine(e);
- throw;
- }
-}
+ void HandleStartup(Action action)
+ {
+ try
+ {
+ action();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ throw;
+ }
+ }
-IConfigurationRoot CreateConfiguration()
-{
- var configurationBuilder = new ConfigurationBuilder();
+ IConfigurationRoot CreateConfiguration()
+ {
+ var configurationBuilder = new ConfigurationBuilder();
#if DEBUG
- configurationBuilder.AddJsonFile("appsettings.Development.json", optional: true);
- configurationBuilder.AddJsonFile("appsettings.Local.json", optional: true);
+ configurationBuilder.AddJsonFile("appsettings.Development.json", optional: true);
+ configurationBuilder.AddJsonFile("appsettings.Local.json", optional: true);
#endif
- configurationBuilder.AddCommandLine(args);
- return configurationBuilder.Build();
-}
+ configurationBuilder.AddCommandLine(args);
+ return configurationBuilder.Build();
+ }
-IContainer CreateRootDiContainer(IConfigurationRoot configuration)
-{
- var serviceCollection = DependencyInjection
- .RegisterDefaultServices(configuration)
- .AddLocalProviderServices()
- .AddServerServices()
- .AddServerCoreServices()
- .AddLogging(loggingBuilder => loggingBuilder.AddSerilog());
+ IContainer CreateRootDiContainer(IConfigurationRoot configuration)
+ {
+ var serviceCollection = DependencyInjection
+ .RegisterDefaultServices(configuration)
+ .AddLocalProviderServices()
+ .AddServerServices()
+ .AddServerCoreServices()
+ .AddLogging(loggingBuilder => loggingBuilder.AddSerilog());
- serviceCollection.AddSingleton(
- new ApplicationStopper(() => applicationCancellation.Cancel())
- );
+ serviceCollection.AddSingleton(
+ new ApplicationStopper(() => applicationCancellation.Cancel())
+ );
- var containerBuilder = new ContainerBuilder();
- containerBuilder.Populate(serviceCollection);
- return containerBuilder.Build();
+ var containerBuilder = new ContainerBuilder();
+ containerBuilder.Populate(serviceCollection);
+ return containerBuilder.Build();
+ }
+ }
}
\ No newline at end of file