From 5a2855176b7faac2ad8aa455fd20c4abcb8bb6b2 Mon Sep 17 00:00:00 2001 From: Atria1234 Date: Tue, 28 Dec 2021 08:58:19 +0100 Subject: [PATCH] Added logic to show command line parser help text in console when "--help" argument is specified --- AnnoDesigner/App.xaml.cs | 15 +++++- AnnoDesigner/ArgumentParser.cs | 40 +++++++++++---- AnnoDesigner/ConsoleManager.cs | 92 ++++++++++++++++++++++++++++++++++ README.md | 10 ++++ 4 files changed, 146 insertions(+), 11 deletions(-) create mode 100644 AnnoDesigner/ConsoleManager.cs diff --git a/AnnoDesigner/App.xaml.cs b/AnnoDesigner/App.xaml.cs index bc4b34b6..18076c56 100644 --- a/AnnoDesigner/App.xaml.cs +++ b/AnnoDesigner/App.xaml.cs @@ -123,7 +123,7 @@ public static string ApplicationPath } } - public static object StartupArguments { get; private set; } + public static IProgramArgs StartupArguments { get; private set; } /// /// The DPI information for the current monitor. @@ -132,7 +132,18 @@ public static string ApplicationPath private async void Application_Startup(object sender, StartupEventArgs e) { - StartupArguments = ArgumentParser.Parse(e.Args); + try + { + StartupArguments = ArgumentParser.Parse(e.Args); + } + catch (HelpException ex) + { + ConsoleManager.Show(); + Console.WriteLine(ex.HelpText); + Console.WriteLine("Press enter to exit"); + Console.ReadLine(); + Environment.Exit(0); + } using var mutexAnnoDesigner = new Mutex(true, MutexHelper.MUTEX_ANNO_DESIGNER, out var createdNewMutex); //Are there other processes still running? diff --git a/AnnoDesigner/ArgumentParser.cs b/AnnoDesigner/ArgumentParser.cs index c5f0db26..4483eeaf 100644 --- a/AnnoDesigner/ArgumentParser.cs +++ b/AnnoDesigner/ArgumentParser.cs @@ -1,23 +1,27 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using CommandLine; +using CommandLine.Text; namespace AnnoDesigner { - [Verb("askAdmin")] - public class AdminRestartArgs + public interface IProgramArgs { } + + [Verb("askAdmin", Hidden = true)] + public class AdminRestartArgs : IProgramArgs { public const string Arguments = "askAdmin"; } - [Verb("open")] - public class OpenArgs + [Verb("open", HelpText = "Opens layout after AnnoDesigner starts")] + public class OpenArgs : IProgramArgs { [Value(0, HelpText = "Input AD file", Required = true)] public string Filename { get; set; } } - [Verb("export")] - public class ExportArgs + [Verb("export", HelpText = "Exports layout to image and exits")] + public class ExportArgs : IProgramArgs { [Value(0, HelpText = "Input AD file", Required = true)] public string Filename { get; set; } @@ -59,11 +63,29 @@ public class ExportArgs public bool RenderVersion { get; set; } } + public class HelpException : Exception + { + public HelpText HelpText { get; } + + public HelpException(HelpText helpText) + { + HelpText = helpText; + } + } + public static class ArgumentParser { - public static object Parse(IEnumerable arguments) + public static IProgramArgs Parse(IEnumerable arguments) { - return Parser.Default.ParseArguments(arguments).MapResult(x => x, _ => null); + var parsed = Parser.Default.ParseArguments(arguments); + return parsed.MapResult(x => x, x => x, x => x, errors => + { + if (errors.IsHelp() || errors.IsVersion()) + { + throw new HelpException(HelpText.AutoBuild(parsed)); + } + return null; + }); } } } diff --git a/AnnoDesigner/ConsoleManager.cs b/AnnoDesigner/ConsoleManager.cs new file mode 100644 index 00000000..b35169d6 --- /dev/null +++ b/AnnoDesigner/ConsoleManager.cs @@ -0,0 +1,92 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Security; + +namespace AnnoDesigner +{ + /// + /// Console manager class for showing console when help text should be shown. + /// + /// + /// Source: https://stackoverflow.com/a/718505 + /// + [SuppressUnmanagedCodeSecurity] + public static class ConsoleManager + { + private const string Kernel32_DllName = "kernel32.dll"; + + [DllImport(Kernel32_DllName)] + private static extern bool AllocConsole(); + + [DllImport(Kernel32_DllName)] + private static extern bool FreeConsole(); + + [DllImport(Kernel32_DllName)] + private static extern IntPtr GetConsoleWindow(); + + [DllImport(Kernel32_DllName)] + private static extern int GetConsoleOutputCP(); + + public static bool HasConsole + { + get { return GetConsoleWindow() != IntPtr.Zero; } + } + + /// + /// Creates a new console instance if the process is not attached to a console already. + /// + public static void Show() + { + if (!HasConsole) + { + AllocConsole(); + InvalidateOutAndError(); + } + } + + /// + /// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown. + /// + public static void Hide() + { + if (HasConsole) + { + SetOutAndErrorNull(); + FreeConsole(); + } + } + + public static void Toggle() + { + if (HasConsole) + { + Hide(); + } + else + { + Show(); + } + } + + static void InvalidateOutAndError() + { + var type = typeof(Console); + + type.GetField("_out", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) + .SetValue(null, null); + + type.GetField("_error", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) + .SetValue(null, null); + + type.GetMethod("InitializeStdOutError", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) + .Invoke(null, new object[] { true }); + } + + static void SetOutAndErrorNull() + { + Console.SetOut(TextWriter.Null); + Console.SetError(TextWriter.Null); + } + } +} diff --git a/README.md b/README.md index 797ab3a4..483e567d 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,16 @@ The **Anno Designer** is a standalone windows application that can be used for c **Download the latest version from the [here](https://github.com/AnnoDesigner/anno-designer/releases/tag/AnnoDesignerv9.2)** (select the .exe file). Run it, and use it to design layouts! +Anno Designer can be started either without any arguments or by specifying one of supported verbs. When started without arguments, empty layout is open. + +Run `AnnoDesigner.exe --help` for list of supported verbs + +- `open` - opens specified layout file instead of empty layout +- `export` - exports specific layout file to PNG file and exits + +Run `AnnoDesigner.exe --help` (for example `AnnoDesigner.exe open --help`) for more info about that verb and its arguments. + + ## Technology This application is written in C# (.NET Framework 4.8) and uses WPF.