diff --git a/CollapseLauncher/Classes/Properties/AppActivation.cs b/CollapseLauncher/Classes/Properties/AppActivation.cs index c7e469ade..c89397957 100644 --- a/CollapseLauncher/Classes/Properties/AppActivation.cs +++ b/CollapseLauncher/Classes/Properties/AppActivation.cs @@ -1,9 +1,11 @@ -using System; +using Microsoft.Win32; +using Microsoft.Windows.AppLifecycle; +using System; using System.Linq; using System.Text.RegularExpressions; -using Microsoft.Windows.AppLifecycle; using Windows.ApplicationModel.Activation; using static CollapseLauncher.InnerLauncherConfig; +using static Hi3Helper.Logger; using static Hi3Helper.Shared.Region.LauncherConfig; namespace CollapseLauncher @@ -13,6 +15,32 @@ public static class AppActivation public static void Enable() { AppInstance.GetCurrent().Activated += App_Activated; + + string protocolName = "collapse"; + RegistryKey reg = Registry.ClassesRoot.OpenSubKey(protocolName + "\\shell\\open\\command", true); + + if (reg != null) + { + if ((string)reg.GetValue("") == string.Format("\"{0}\" %1", AppExecutablePath)) + { + LogWriteLine("The protocol is already activated."); + return; + } + } + + LogWriteLine("Protocol does not exist or paths are different. Activating protocol..."); + + Registry.ClassesRoot.DeleteSubKeyTree(protocolName, false); + + RegistryKey protocol = Registry.ClassesRoot.CreateSubKey(protocolName, true); + + protocol.SetValue("", "CollapseLauncher protocol"); + protocol.SetValue("URL Protocol", ""); + protocol.SetValue("Version", AppCurrentVersionString); + + RegistryKey command = protocol.CreateSubKey("shell\\open\\command", true); + + command.SetValue("", string.Format("\"{0}\" %1", AppExecutablePath)); } private static void App_Activated(object sender, AppActivationArguments e) diff --git a/CollapseLauncher/Classes/Properties/ArgumentParser.cs b/CollapseLauncher/Classes/Properties/ArgumentParser.cs index ad91c325f..3ea02536b 100644 --- a/CollapseLauncher/Classes/Properties/ArgumentParser.cs +++ b/CollapseLauncher/Classes/Properties/ArgumentParser.cs @@ -1,13 +1,20 @@ using System; +using System.Collections.Generic; using System.CommandLine; using System.CommandLine.NamingConventionBinder; +using System.Linq; +using System.Text.RegularExpressions; using static CollapseLauncher.InnerLauncherConfig; +using static Hi3Helper.Logger; namespace CollapseLauncher { public static partial class ArgumentParser { - static RootCommand rootCommand = new RootCommand(); + private static List allowedProtocolCommands = ["tray", "open"]; + + private static RootCommand rootCommand = new RootCommand(); + public static void ParseArguments(params string[] args) { if (args.Length == 0) @@ -16,6 +23,37 @@ public static void ParseArguments(params string[] args) return; } + if (args[0].StartsWith("collapse://")) + { + args[0] = args[0].Replace("collapse://", ""); + + if (args[0] == "/" || args[0] == "") + { + m_appMode = AppMode.Launcher; + return; + } + + // Convert web browser format (contains %20 or %22 but no " or space) + if ((args[0].Contains("%20") || args[0].Contains("%22")) + && !(args[0].Contains(' ') || args[0].Contains('"'))) + { + string convertedArg = args[0].Replace("%20", " ").Replace("%22", "\""); + + args = Regex.Matches(convertedArg, @"[\""].+?[\""]|[^ ]+") + .Cast() + .Select(x => x.Value.Trim('"')).ToArray(); + } + + args = args.Select(x => x.Trim('/')).Where(x => x != "").ToArray(); + + if (allowedProtocolCommands.IndexOf(args[0]) == -1) + { + LogWriteLine("This command does not exist or cannot be activated using a protocol.", Hi3Helper.LogType.Error); + m_appMode = AppMode.Launcher; + return; + } + } + switch (args[0].ToLower()) { case "hi3cacheupdate": @@ -72,36 +110,39 @@ public static void ParseArguments(params string[] args) public static void ParseHi3CacheUpdaterArguments(params string[] args) { - rootCommand.AddArgument(new Argument("hi3cacheupdate", "Update the app or change the Release Channel of the app") { HelpName = null }); - AddHi3CacheUpdaterOptions(); + Command hi3cacheupdate = new Command("hi3cacheupdate", "Update the app or change the Release Channel of the app"); + rootCommand.AddCommand(hi3cacheupdate); + AddHi3CacheUpdaterOptions(hi3cacheupdate); } public static void ParseUpdaterArguments(params string[] args) { - rootCommand.AddArgument(new Argument("update", "Update the app or change the Release Channel of the app") { HelpName = null }); - AddUpdaterOptions(); + Command updater = new Command("update", "Update the app or change the Release Channel of the app"); + rootCommand.AddCommand(updater); + AddUpdaterOptions(updater); } public static void ParseElevateUpdaterArguments(params string[] args) { - rootCommand.AddArgument(new Argument("elevateupdate", "Elevate updater to run as administrator") { HelpName = null }); - AddUpdaterOptions(); + Command elevateUpdater = new Command("elevateupdate", "Elevate updater to run as administrator"); + rootCommand.AddCommand(elevateUpdater); + AddUpdaterOptions(elevateUpdater); } - public static void AddHi3CacheUpdaterOptions() + public static void AddHi3CacheUpdaterOptions(Command command) { - rootCommand.SetHandler(() => + command.SetHandler(() => { }); } - public static void AddUpdaterOptions() + public static void AddUpdaterOptions(Command command) { Option o_Input = new Option(new string[] { "--input", "-i" }, "App path") { IsRequired = true }; Option o_Channel = new Option(new string[] { "--channel", "-c" }, "App release channel") { IsRequired = true }.FromAmong(); - rootCommand.AddOption(o_Input); - rootCommand.AddOption(o_Channel); - rootCommand.Handler = CommandHandler.Create((string Input, AppReleaseChannel ReleaseChannel) => + command.AddOption(o_Input); + command.AddOption(o_Channel); + command.Handler = CommandHandler.Create((string Input, AppReleaseChannel ReleaseChannel) => { m_arguments.Updater = new ArgumentUpdater { @@ -129,32 +170,34 @@ public static void ParseTakeOwnershipArguments(params string[] args) public static void ParseMigrateArguments(bool isBHI3L = false, params string[] args) { + Command migrate; if (!isBHI3L) - rootCommand.AddArgument(new Argument("migrate", "Migrate Game from one installation to another location") { HelpName = null }); + migrate = new Command("migrate", "Migrate Game from one installation to another location"); else - rootCommand.AddArgument(new Argument("migratebhi3l", "Migrate Game from BetterHi3Launcher to another location") { HelpName = null }); - AddMigrateOptions(isBHI3L); + migrate = new Command("migratebhi3l", "Migrate Game from BetterHi3Launcher to another location"); + AddMigrateOptions(isBHI3L, migrate); + rootCommand.AddCommand(migrate); } public static void ParseOOBEArguments(params string[] args) { - rootCommand.AddArgument(new Argument("oobesetup", "Starts Collapse in OOBE mode, to simulate first-time setup") { HelpName = null }); + rootCommand.AddCommand(new Command("oobesetup", "Starts Collapse in OOBE mode, to simulate first-time setup")); } - private static void AddMigrateOptions(bool isBHI3L) + private static void AddMigrateOptions(bool isBHI3L, Command command) { var inputOption = new Option(new string[] { "--input", "-i" }, description: "Installation Source") { IsRequired = true }; var outputOption = new Option(new string[] { "--output", "-o" }, description: "Installation Target") { IsRequired = true }; var rootCommand = new RootCommand(); - rootCommand.AddOption(inputOption); - rootCommand.AddOption(outputOption); + command.AddOption(inputOption); + command.AddOption(outputOption); if (isBHI3L) { var gameVerOption = new Option(new string[] { "--gamever", "-g" }, description: "Game version string (Format: x.x.x)") { IsRequired = true }; var regLocOption = new Option(new string[] { "--regloc", "-r" }, description: "Location of game registry for BetterHI3Launcher keys") { IsRequired = true }; - rootCommand.AddOption(gameVerOption); - rootCommand.AddOption(regLocOption); - rootCommand.Handler = CommandHandler.Create( + command.AddOption(gameVerOption); + command.AddOption(regLocOption); + command.Handler = CommandHandler.Create( (string Input, string Output, string GameVer, string RegLoc) => { m_arguments.Migrate = new ArgumentMigrate @@ -168,7 +211,7 @@ private static void AddMigrateOptions(bool isBHI3L) }); return; } - rootCommand.Handler = CommandHandler.Create( + command.Handler = CommandHandler.Create( (string Input, string Output) => { m_arguments.Migrate = new ArgumentMigrate