diff --git a/Dotnet/AppApi/AppApi.cs b/Dotnet/AppApi/AppApi.cs index c504f26d..1fe6c4f4 100644 --- a/Dotnet/AppApi/AppApi.cs +++ b/Dotnet/AppApi/AppApi.cs @@ -278,16 +278,33 @@ namespace VRCX } /// - /// Restarts the VRCX application for an update by launching a new process with the "/Upgrade" argument and exiting the current process. + /// Restarts the VRCX application for an update by launching a new process with the upgrade argument and exiting the current process. /// public void RestartApplication() { + List args = [ StartupArgs.VrcxLaunchArguements.IsUpgradePrefix ]; + + if (StartupArgs.LaunchArguements.IsDebug == true) + { + args.Add(StartupArgs.VrcxLaunchArguements.IsDebugPrefix); + } + + if (!string.IsNullOrWhiteSpace(StartupArgs.LaunchArguements.ConfigDirectory)) + { + args.Add($"{StartupArgs.VrcxLaunchArguements.ConfigDirectoryPrefix}={StartupArgs.LaunchArguements.ConfigDirectory}"); + } + + if (!string.IsNullOrWhiteSpace(StartupArgs.LaunchArguements.ProxyUrl)) + { + args.Add($"{StartupArgs.VrcxLaunchArguements.ProxyUrlPrefix}={StartupArgs.LaunchArguements.ProxyUrl}"); + } + var vrcxProcess = new Process { StartInfo = new ProcessStartInfo { FileName = Path.Combine(Program.BaseDirectory, "VRCX.exe"), - Arguments = "/Upgrade", + Arguments = string.Join(' ', args), UseShellExecute = true, WorkingDirectory = Program.BaseDirectory } @@ -362,8 +379,8 @@ namespace VRCX /// The launch command. public string GetLaunchCommand() { - var command = StartupArgs.LaunchCommand; - StartupArgs.LaunchCommand = string.Empty; + var command = StartupArgs.LaunchArguements.LaunchCommand; + StartupArgs.LaunchArguements.LaunchCommand = string.Empty; return command; } diff --git a/Dotnet/StartupArgs.cs b/Dotnet/StartupArgs.cs index e6bf753c..6fe86c80 100644 --- a/Dotnet/StartupArgs.cs +++ b/Dotnet/StartupArgs.cs @@ -4,13 +4,13 @@ // This work is licensed under the terms of the MIT license. // For a copy, see . -using CefSharp; using CefSharp.Internals; using System; using System.Diagnostics; using System.IO; using System.IO.Pipes; -using System.Net; +using System.Linq; +using System.Management; using System.Text; using System.Windows.Forms; @@ -18,59 +18,120 @@ namespace VRCX { internal class StartupArgs { - public static string LaunchCommand; - public static string ProxyUrl; - public static Process[] processList; + public static VrcxLaunchArguements LaunchArguements = new(); public static void ArgsCheck() { var args = Environment.GetCommandLineArgs(); - processList = Process.GetProcessesByName("VRCX"); Debug.Assert(Program.LaunchDebug = true); - var disableClosing = false; - foreach (var arg in args) - { - if (arg == "/Upgrade") - disableClosing = true; - - if (arg.Length > 12 && arg.Substring(0, 12) == "/uri=vrcx://") - LaunchCommand = arg.Substring(12); + var currentProcessArgs = ParseArgs(args); + LaunchArguements = currentProcessArgs; - if (arg.Length > 8 && arg.Substring(0, 8) == "--config") + if (LaunchArguements.IsDebug) + Program.LaunchDebug = true; + + if (LaunchArguements.ConfigDirectory != null) + { + if (File.Exists(LaunchArguements.ConfigDirectory)) { - var filePath = arg.Substring(9); - if (File.Exists(filePath)) - { - MessageBox.Show("Move your \"VRCX.sqlite3\" into a folder then specify the folder in the launch parameter e.g.\n--config=\"C:\\VRCX\\\"", "--config is now a directory", MessageBoxButtons.OK, MessageBoxIcon.Error); - Environment.Exit(0); - } - Program.AppDataDirectory = filePath; + MessageBox.Show("Move your \"VRCX.sqlite3\" into a folder then specify the folder in the launch parameter e.g.\n--config=\"C:\\VRCX\\\"", "--config is now a directory", MessageBoxButtons.OK, MessageBoxIcon.Error); + Environment.Exit(0); } - if (arg.Length >= 7 && arg.Substring(0, 7) == "--debug") - Program.LaunchDebug = true; - - if (arg.Length >= 16 && arg.Substring(0, 14) == "--proxy-server") - ProxyUrl = arg.Substring(15).Replace("'", string.Empty).Replace("\"", string.Empty); + Program.AppDataDirectory = LaunchArguements.ConfigDirectory; } - var type = CommandLineArgsParser.GetArgumentValue(args, CefSharpArguments.SubProcessTypeArgument); - if (!string.IsNullOrEmpty(type)) - disableClosing = true; // we're launching a subprocess, allow it + var disableClosing = false; - if (!string.IsNullOrEmpty(Program.AppDataDirectory)) - disableClosing = true; // we're launching with a custom config path, allow it + if (LaunchArguements.IsUpgrade || // we're upgrading, allow it + !string.IsNullOrEmpty(CommandLineArgsParser.GetArgumentValue(args, CefSharpArguments.SubProcessTypeArgument))) // we're launching a subprocess, allow it + disableClosing = true; - // if we're launching a second instance, focus the first instance then exit - if (!disableClosing && processList.Length > 1) + // if we're launching a second instance with same config directory, focus the first instance then exit + if (!disableClosing && IsDuplicateProcessRunning(LaunchArguements)) { IPCToMain(); Environment.Exit(0); } } + private static VrcxLaunchArguements ParseArgs(string[] args) + { + VrcxLaunchArguements arguements = new VrcxLaunchArguements(); + foreach (var arg in args) + { + if (arg == VrcxLaunchArguements.IsUpgradePrefix) + arguements.IsUpgrade = true; + + if (arg.StartsWith(VrcxLaunchArguements.IsDebugPrefix)) + arguements.IsDebug = true; + + if (arg.StartsWith(VrcxLaunchArguements.LaunchCommandPrefix) && arg.Length > VrcxLaunchArguements.LaunchCommandPrefix.Length) + arguements.LaunchCommand = arg.Substring(VrcxLaunchArguements.LaunchCommandPrefix.Length); + + if (arg.StartsWith(VrcxLaunchArguements.ConfigDirectoryPrefix) && arg.Length > VrcxLaunchArguements.ConfigDirectoryPrefix.Length) + arguements.ConfigDirectory = arg.Substring(VrcxLaunchArguements.ConfigDirectoryPrefix.Length + 1); + + if (arg.StartsWith(VrcxLaunchArguements.ProxyUrlPrefix) && arg.Length > VrcxLaunchArguements.ProxyUrlPrefix.Length) + arguements.ProxyUrl = arg.Substring(VrcxLaunchArguements.ProxyUrlPrefix.Length + 1).Replace("'", string.Empty).Replace("\"", string.Empty); + } + return arguements; + } + + internal class VrcxLaunchArguements + { + public const string IsUpgradePrefix = "/Upgrade"; + public bool IsUpgrade { get; set; } = false; + + public const string IsDebugPrefix = "--debug"; + public bool IsDebug { get; set; } = false; + + public const string LaunchCommandPrefix = "/uri=vrcx://"; + public string LaunchCommand { get; set; } = null; + + public const string ConfigDirectoryPrefix = "--config"; + public string ConfigDirectory { get; set; } = null; + + public const string ProxyUrlPrefix = "--proxy-server"; + public string ProxyUrl { get; set; } = null; + } + + private static bool IsDuplicateProcessRunning(VrcxLaunchArguements launchArguements) + { + var processes = Process.GetProcessesByName("VRCX"); + foreach (var process in processes) + { + var commandLine = string.Empty; + + try + { + using (var searcher = new ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + process.Id)) + { + using (var objects = searcher.Get()) + { + commandLine = objects.Cast().SingleOrDefault()?["CommandLine"]?.ToString() ?? string.Empty; + } + } + } + catch { } + + if (commandLine.Contains(CefSharpArguments.SubProcessTypeArgument)) // ignore subprocesses + { + continue; + } + + var processArguements = ParseArgs(commandLine.Split(' ')); + if (processArguements.ConfigDirectory == launchArguements.ConfigDirectory) + { + return true; + } + } + + return false; + } + private static void IPCToMain() { new IPCServer().CreateIPCServer(); @@ -79,7 +140,7 @@ namespace VRCX if (ipcClient.IsConnected) { - var buffer = Encoding.UTF8.GetBytes($"{{\"type\":\"LaunchCommand\",\"command\":\"{LaunchCommand}\"}}" + (char)0x00); + var buffer = Encoding.UTF8.GetBytes($"{{\"type\":\"LaunchCommand\",\"command\":\"{LaunchArguements.LaunchCommand}\"}}" + (char)0x00); ipcClient.BeginWrite(buffer, 0, buffer.Length, IPCClient.Close, ipcClient); } } diff --git a/Dotnet/WebApi.cs b/Dotnet/WebApi.cs index 55e6e160..9fe7696d 100644 --- a/Dotnet/WebApi.cs +++ b/Dotnet/WebApi.cs @@ -59,8 +59,8 @@ namespace VRCX private void SetProxy() { - if (!string.IsNullOrEmpty(StartupArgs.ProxyUrl)) - ProxyUrl = StartupArgs.ProxyUrl; + if (!string.IsNullOrEmpty(StartupArgs.LaunchArguements.ProxyUrl)) + ProxyUrl = StartupArgs.LaunchArguements.ProxyUrl; if (string.IsNullOrEmpty(ProxyUrl)) { diff --git a/VRCX.csproj b/VRCX.csproj index 131bb70a..378526e1 100644 --- a/VRCX.csproj +++ b/VRCX.csproj @@ -90,6 +90,7 @@ +