From 577a4da60c0a17dfdd0e5cce85b42c7717a7fca2 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Tue, 13 Oct 2026 21:13:34 -0700 Subject: [PATCH] fix: restart relaunches correctly when the server path contains a space (#2704) `Core.DoKill(true)` built the relaunch command line by putting the assembly path into a raw argument string without quotes, so `dotnet` split it at the first space. That breaks `restart`, `AutoRestart` and `CrashGuard` recovery for any server installed under a path with a space. - Pass the assembly path through `ProcessStartInfo.ArgumentList`, which quotes it. - Relaunch through the host that started the process (`Environment.ProcessPath`): the `ModernUO` apphost runs directly, and `dotnet` gets the assembly path. Before this, a server started from the apphost came back under `dotnet`. - Use one code path on all platforms. `UseShellExecute = true` on Unix made no difference for a program found on PATH. This doesn't fix the second half of #2700, where the relaunched server loses the console (and gets killed under systemd or Docker). That comes from the server spawning a copy of itself and exiting, and a follow-up PR will add an opt-in restart exit code for a supervisor to act on. **Testing:** relaunched from a directory with spaces, started both through `dotnet x.dll` and through the apphost, on Windows. The old code fails there with the error from the issue. --- Projects/Server/Main.cs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/Projects/Server/Main.cs b/Projects/Server/Main.cs index 608256651..2daef9a2d 100644 --- a/Projects/Server/Main.cs +++ b/Projects/Server/Main.cs @@ -473,22 +473,17 @@ public static class Core try { logger.Information("Restarting"); - if (IsWindows) - { - using var process = Process.Start("dotnet", $"{ApplicationAssembly.Location}"); - } - else - { - using var process = new Process(); - process.StartInfo = new ProcessStartInfo - { - FileName = "dotnet", - Arguments = $"{ApplicationAssembly.Location}", - UseShellExecute = true - }; - process.Start(); + // Relaunch through whichever host started us: the apphost (ModernUO.exe) runs directly, + // `dotnet ModernUO.dll` needs the assembly path. ArgumentList quotes paths with spaces. + var hostPath = Environment.ProcessPath ?? "dotnet"; + var startInfo = new ProcessStartInfo(hostPath) { UseShellExecute = false }; + if (Path.GetFileNameWithoutExtension(hostPath).Equals("dotnet", StringComparison.OrdinalIgnoreCase)) + { + startInfo.ArgumentList.Add(ApplicationAssembly.Location); } + + using var process = Process.Start(startInfo); logger.Information("Restart done"); } catch (Exception e)