From a6f8b6fa3903d846cdc2fbe715ca951d83af3107 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Thu, 11 Aug 2022 17:40:06 -0700 Subject: Redesign command-line help to meet the needs of WiX v4 --- .../BaseCommandLineCommand.cs | 40 +++++++ .../BaseExtensionCommandLine.cs | 9 +- .../Data/CommandLineHelp.cs | 52 +++++++++ .../Data/CommandLineHelpCommand.cs | 31 +++++ .../Data/CommandLineHelpSwitch.cs | 47 ++++++++ .../Data/ExtensionCommandLineSwitch.cs | 20 ---- .../Data/ICommandLineCommand.cs | 12 +- .../IExtensionCommandLine.cs | 6 +- src/tools/heat/HeatCommand.cs | 22 ++-- src/tools/heat/HeatCommandLine.cs | 6 +- src/tools/heat/HelpCommand.cs | 17 ++- src/wix/WixToolset.Converters/ConvertCommand.cs | 44 +++---- .../ConverterExtensionCommandLine.cs | 15 ++- src/wix/WixToolset.Converters/FixupCommandBase.cs | 39 ++----- src/wix/WixToolset.Converters/FormatCommand.cs | 46 +++----- .../BurnExtensionCommandLine.cs | 10 +- .../CommandLine/BurnCommand.cs | 46 ++++---- .../CommandLine/BurnSubcommandBase.cs | 3 + .../CommandLine/DetachSubcommand.cs | 10 ++ .../CommandLine/ExtractSubcommand.cs | 11 ++ .../CommandLine/ReattachSubcommand.cs | 10 ++ .../CommandLine/RemotePayloadSubcommand.cs | 31 +++++ .../ExtensionCacheManagerCommand.cs | 69 ++++------- .../ExtensionCacheManagerExtensionCommandLine.cs | 10 +- .../CommandLine/DecompilerSubcommand.cs | 16 +++ .../CommandLine/InscribeSubcommand.cs | 10 ++ .../CommandLine/TransformSubcommand.cs | 47 ++++++++ .../CommandLine/ValidateSubcommand.cs | 13 +++ .../CommandLine/WindowsInstallerCommand.cs | 47 ++++---- .../CommandLine/WindowsInstallerSubcommandBase.cs | 3 + .../WindowsInstallerExtensionCommandLine.cs | 13 ++- .../WixToolset.Core/CommandLine/BuildCommand.cs | 66 ++++++----- src/wix/WixToolset.Core/CommandLine/CommandLine.cs | 50 +++++--- .../CommandLine/CommandLineParser.cs | 21 ++-- src/wix/WixToolset.Core/CommandLine/HelpCommand.cs | 126 ++++++++++++++------- .../WixToolset.Core/CommandLine/VersionCommand.cs | 16 +-- .../ExamplePreprocessorExtensionAndCommandLine.cs | 9 +- .../CommandLineFixture.cs | 5 +- 38 files changed, 685 insertions(+), 363 deletions(-) create mode 100644 src/api/wix/WixToolset.Extensibility/BaseCommandLineCommand.cs create mode 100644 src/api/wix/WixToolset.Extensibility/Data/CommandLineHelp.cs create mode 100644 src/api/wix/WixToolset.Extensibility/Data/CommandLineHelpCommand.cs create mode 100644 src/api/wix/WixToolset.Extensibility/Data/CommandLineHelpSwitch.cs delete mode 100644 src/api/wix/WixToolset.Extensibility/Data/ExtensionCommandLineSwitch.cs diff --git a/src/api/wix/WixToolset.Extensibility/BaseCommandLineCommand.cs b/src/api/wix/WixToolset.Extensibility/BaseCommandLineCommand.cs new file mode 100644 index 00000000..69a4f49f --- /dev/null +++ b/src/api/wix/WixToolset.Extensibility/BaseCommandLineCommand.cs @@ -0,0 +1,40 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Extensibility +{ + using System.Threading; + using System.Threading.Tasks; + using WixToolset.Extensibility.Data; + using WixToolset.Extensibility.Services; + + /// + /// Base class for a command-line command. + /// + public abstract class BaseCommandLineCommand : ICommandLineCommand + { + /// + /// See + /// + public virtual bool ShowLogo => false; + + /// + /// See + /// + public bool StopParsing { get; protected set; } + + /// + /// See + /// + public abstract Task ExecuteAsync(CancellationToken cancellationToken); + + /// + /// See + /// + public abstract CommandLineHelp GetCommandLineHelp(); + + /// + /// See + /// + public abstract bool TryParseArgument(ICommandLineParser parser, string argument); + } +} diff --git a/src/api/wix/WixToolset.Extensibility/BaseExtensionCommandLine.cs b/src/api/wix/WixToolset.Extensibility/BaseExtensionCommandLine.cs index c716ac7e..2690788b 100644 --- a/src/api/wix/WixToolset.Extensibility/BaseExtensionCommandLine.cs +++ b/src/api/wix/WixToolset.Extensibility/BaseExtensionCommandLine.cs @@ -2,8 +2,6 @@ namespace WixToolset.Extensibility { - using System; - using System.Collections.Generic; using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; @@ -13,9 +11,12 @@ namespace WixToolset.Extensibility public abstract class BaseExtensionCommandLine : IExtensionCommandLine { /// - /// See + /// See /// - public virtual IReadOnlyCollection CommandLineSwitches => Array.Empty(); + public virtual CommandLineHelp GetCommandLineHelp() + { + return null; + } /// /// See diff --git a/src/api/wix/WixToolset.Extensibility/Data/CommandLineHelp.cs b/src/api/wix/WixToolset.Extensibility/Data/CommandLineHelp.cs new file mode 100644 index 00000000..52291947 --- /dev/null +++ b/src/api/wix/WixToolset.Extensibility/Data/CommandLineHelp.cs @@ -0,0 +1,52 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Extensibility.Data +{ + using System.Collections.Generic; + + /// + /// A command line option (switch or command) description. + /// + public class CommandLineHelp + { + /// + /// Creates command line help. + /// + /// Description for the command line option. + /// Optional usage for the command line option. + /// Optional list of switches. + /// Optional list of commands. + public CommandLineHelp(string description, string usage = null, IReadOnlyCollection switches = null, IReadOnlyCollection commands = null) + { + this.Description = description; + this.Usage = usage; + this.Switches = switches; + this.Commands = commands; + } + + /// + /// Description for the command line option. + /// + public string Description { get; set; } + + /// + /// Usage for the command line option. + /// + public string Usage { get; set; } + + /// + /// Optional additional notes for the command line option. + /// + public string Notes { get; set; } + + /// + /// Optional list of command line switches. + /// + public IReadOnlyCollection Switches { get; set; } + + /// + /// Optional list of command line commands. + /// + public IReadOnlyCollection Commands { get; set; } + } +} diff --git a/src/api/wix/WixToolset.Extensibility/Data/CommandLineHelpCommand.cs b/src/api/wix/WixToolset.Extensibility/Data/CommandLineHelpCommand.cs new file mode 100644 index 00000000..a9fc70f9 --- /dev/null +++ b/src/api/wix/WixToolset.Extensibility/Data/CommandLineHelpCommand.cs @@ -0,0 +1,31 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Extensibility.Data +{ + /// + /// A command line command description. + /// + public class CommandLineHelpCommand + { + /// + /// Creates help for command line command. + /// + /// Name of command. + /// Description for command. + public CommandLineHelpCommand(string name, string description) + { + Name = name; + Description = description; + } + + /// + /// Name of command. + /// + public string Name { get; set; } + + /// + /// Description of the command. + /// + public string Description { get; set; } + } +} diff --git a/src/api/wix/WixToolset.Extensibility/Data/CommandLineHelpSwitch.cs b/src/api/wix/WixToolset.Extensibility/Data/CommandLineHelpSwitch.cs new file mode 100644 index 00000000..19c014ad --- /dev/null +++ b/src/api/wix/WixToolset.Extensibility/Data/CommandLineHelpSwitch.cs @@ -0,0 +1,47 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Extensibility.Data +{ + /// + /// A command line switch description. + /// + public class CommandLineHelpSwitch + { + /// + /// Creates help for command line switch. + /// + /// Name of switch. + /// Description for switch. + public CommandLineHelpSwitch(string name, string description) : this(name, null, description) + { + } + + /// + /// Creates help for command line switch. + /// + /// Name of switch. + /// Optional short name of switch. + /// Description for switch. + public CommandLineHelpSwitch(string name, string shortName, string description) + { + Name = name; + ShortName = shortName; + Description = description; + } + + /// + /// Name for switch. + /// + public string Name { get; set; } + + /// + /// Optional short name for switch. + /// + public string ShortName { get; set; } + + /// + /// Description of the switch. + /// + public string Description { get; set; } + } +} diff --git a/src/api/wix/WixToolset.Extensibility/Data/ExtensionCommandLineSwitch.cs b/src/api/wix/WixToolset.Extensibility/Data/ExtensionCommandLineSwitch.cs deleted file mode 100644 index 14b5dabb..00000000 --- a/src/api/wix/WixToolset.Extensibility/Data/ExtensionCommandLineSwitch.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. - -namespace WixToolset.Extensibility.Data -{ - /// - /// A command line option. - /// - public struct ExtensionCommandLineSwitch - { - /// - /// - /// - public string Switch { get; set; } - - /// - /// - /// - public string Description { get; set; } - } -} diff --git a/src/api/wix/WixToolset.Extensibility/Data/ICommandLineCommand.cs b/src/api/wix/WixToolset.Extensibility/Data/ICommandLineCommand.cs index b6c9ef3e..1f58bfb5 100644 --- a/src/api/wix/WixToolset.Extensibility/Data/ICommandLineCommand.cs +++ b/src/api/wix/WixToolset.Extensibility/Data/ICommandLineCommand.cs @@ -12,19 +12,19 @@ namespace WixToolset.Extensibility.Data public interface ICommandLineCommand { /// - /// Indicates the command-line should show help for the command. + /// Indicates the command-line should show the logo. /// - bool ShowHelp { get; set; } + bool ShowLogo { get; } /// - /// Indicates the command-line should show the command-line logo. + /// Indicates the command-line parsing can stop. /// - bool ShowLogo { get; set; } + bool StopParsing { get; } /// - /// Indicates the command-line parsing can stop. + /// Gets the help for this command. /// - bool StopParsing { get; } + CommandLineHelp GetCommandLineHelp(); /// /// Executes the command. diff --git a/src/api/wix/WixToolset.Extensibility/IExtensionCommandLine.cs b/src/api/wix/WixToolset.Extensibility/IExtensionCommandLine.cs index f7b19955..304c30bb 100644 --- a/src/api/wix/WixToolset.Extensibility/IExtensionCommandLine.cs +++ b/src/api/wix/WixToolset.Extensibility/IExtensionCommandLine.cs @@ -2,7 +2,6 @@ namespace WixToolset.Extensibility { - using System.Collections.Generic; using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; @@ -12,10 +11,9 @@ namespace WixToolset.Extensibility public interface IExtensionCommandLine { /// - /// Gets the supported command line types for this extension. + /// Gets the help for this extension. /// - /// The supported command line types for this extension. - IReadOnlyCollection CommandLineSwitches { get; } + CommandLineHelp GetCommandLineHelp(); /// /// Called before the command-line is parsed. diff --git a/src/tools/heat/HeatCommand.cs b/src/tools/heat/HeatCommand.cs index 56277004..6815acd6 100644 --- a/src/tools/heat/HeatCommand.cs +++ b/src/tools/heat/HeatCommand.cs @@ -11,13 +11,16 @@ namespace WixToolset.Harvesters using System.Threading.Tasks; using System.Xml; using WixToolset.Data; + using WixToolset.Extensibility; using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; using WixToolset.Harvesters.Extensibility; using Wix = WixToolset.Harvesters.Serialize; - internal class HeatCommand : ICommandLineCommand + internal class HeatCommand : BaseCommandLineCommand { + private bool showLogo; + public HeatCommand(string harvestType, IList extensions, IServiceProvider serviceProvider) { this.Extensions = extensions; @@ -28,11 +31,7 @@ namespace WixToolset.Harvesters this.ExtensionOptions.Add(harvestType); } - public bool ShowHelp { get; set; } - - public bool ShowLogo { get; set; } - - public bool StopParsing { get; private set; } + public override bool ShowLogo => this.showLogo; private string ExtensionArgument { get; set; } @@ -50,13 +49,18 @@ namespace WixToolset.Harvesters private IServiceProvider ServiceProvider { get; } - public Task ExecuteAsync(CancellationToken cancellationToken) + public override CommandLineHelp GetCommandLineHelp() + { + return null; + } + + public override Task ExecuteAsync(CancellationToken cancellationToken) { var exitCode = this.Harvest(); return Task.FromResult(exitCode); } - public bool TryParseArgument(ICommandLineParser parser, string arg) + public override bool TryParseArgument(ICommandLineParser parser, string arg) { if (this.ExtensionArgument == null) { @@ -67,7 +71,7 @@ namespace WixToolset.Harvesters string parameter = arg.Substring(1); if ("nologo" == parameter) { - this.ShowLogo = false; + this.showLogo = false; } else if ("o" == parameter || "out" == parameter) { diff --git a/src/tools/heat/HeatCommandLine.cs b/src/tools/heat/HeatCommandLine.cs index b11dda4e..f299266d 100644 --- a/src/tools/heat/HeatCommandLine.cs +++ b/src/tools/heat/HeatCommandLine.cs @@ -13,19 +13,17 @@ namespace WixToolset.Harvesters internal class HeatCommandLine : IHeatCommandLine { - private readonly List extensions; - private readonly IMessaging messaging; private readonly IServiceProvider serviceProvider; + private readonly List extensions; public HeatCommandLine(IServiceProvider serviceProvider, IEnumerable heatExtensions) { + this.serviceProvider = serviceProvider; this.extensions = new List { new IIsHeatExtension(), new UtilHeatExtension(serviceProvider), new VSHeatExtension() }; if (heatExtensions != null) { this.extensions.AddRange(heatExtensions); } - this.messaging = serviceProvider.GetService(); - this.serviceProvider = serviceProvider; } public ICommandLineCommand ParseStandardCommandLine(ICommandLineArguments arguments) diff --git a/src/tools/heat/HelpCommand.cs b/src/tools/heat/HelpCommand.cs index d991b4fa..25d8cd87 100644 --- a/src/tools/heat/HelpCommand.cs +++ b/src/tools/heat/HelpCommand.cs @@ -8,12 +8,13 @@ namespace WixToolset.Harvesters using System.Diagnostics; using System.Threading; using System.Threading.Tasks; + using WixToolset.Extensibility; using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; using WixToolset.Harvesters.Data; using WixToolset.Harvesters.Extensibility; - internal class HelpCommand : ICommandLineCommand + internal class HelpCommand : BaseCommandLineCommand { const string HelpMessageOptionFormat = " {0,-7} {1}"; @@ -24,17 +25,12 @@ namespace WixToolset.Harvesters private IList Extensions { get; } - public bool ShowHelp { get; set; } - - public bool ShowLogo + public override CommandLineHelp GetCommandLineHelp() { - get => false; - set { } + return null; } - public bool StopParsing => true; - - public Task ExecuteAsync(CancellationToken cancellationToken) + public override Task ExecuteAsync(CancellationToken cancellationToken) { var exitCode = this.DisplayHelp(); return Task.FromResult(exitCode); @@ -50,8 +46,9 @@ namespace WixToolset.Harvesters Console.WriteLine(); } - public bool TryParseArgument(ICommandLineParser parser, string argument) + public override bool TryParseArgument(ICommandLineParser parser, string argument) { + this.StopParsing = true; return true; } diff --git a/src/wix/WixToolset.Converters/ConvertCommand.cs b/src/wix/WixToolset.Converters/ConvertCommand.cs index b6826f43..bec6cd19 100644 --- a/src/wix/WixToolset.Converters/ConvertCommand.cs +++ b/src/wix/WixToolset.Converters/ConvertCommand.cs @@ -5,27 +5,34 @@ namespace WixToolset.Converters using System; using System.Threading; using System.Threading.Tasks; - using WixToolset.Extensibility.Services; + using WixToolset.Extensibility.Data; internal class ConvertCommand : FixupCommandBase { private const string SettingsFileDefault = "wix.convert.settings.xml"; - public ConvertCommand(IServiceProvider serviceProvider) + public ConvertCommand(IServiceProvider serviceProvider) : base(serviceProvider) { - this.Messaging = serviceProvider.GetService(); } - private IMessaging Messaging { get; } - - public override Task ExecuteAsync(CancellationToken cancellationToken) + public override CommandLineHelp GetCommandLineHelp() { - if (this.ShowHelp) + return new CommandLineHelp("Convert v3 source code to v4 source code.", "convert [options] sourceFile [sourceFile ...]") { - DisplayHelp(); - return Task.FromResult(-1); - } + Switches = new[] + { + new CommandLineHelpSwitch("--dry-run", "-n", "Only display errors, do not update files."), + new CommandLineHelpSwitch("--recurse", "-r", "Search for matching files in current dir and subdirs."), + new CommandLineHelpSwitch("-set1", "Primary settings file."), + new CommandLineHelpSwitch("-set2", "Secondary settings file (overrides primary)."), + new CommandLineHelpSwitch("-indent:", "Indentation multiple (overrides default of 4)."), + }, + Notes = " sourceFile may use wildcards like *.wxs" + }; + } + public override Task ExecuteAsync(CancellationToken cancellationToken) + { this.ParseSettings(SettingsFileDefault); var converter = new WixConverter(this.Messaging, this.IndentationAmount, this.ErrorsAsWarnings, this.IgnoreErrors); @@ -39,22 +46,5 @@ namespace WixToolset.Converters return converter.ConvertFile(file, fix); } } - - private static void DisplayHelp() - { - Console.WriteLine(); - Console.WriteLine("Usage: wix convert [options] sourceFile [sourceFile ...]"); - Console.WriteLine(); - Console.WriteLine("Options:"); - Console.WriteLine(" -h|--help Show command line help."); - Console.WriteLine(" --nologo Suppress displaying the logo information."); - Console.WriteLine(" -n|--dry-run Only display errors, do not update files."); - Console.WriteLine(" -r|--recurse Search for matching files in current dir and subdirs."); - Console.WriteLine(" -set1 Primary settings file."); - Console.WriteLine(" -set2 Secondary settings file (overrides primary)."); - Console.WriteLine(" -indent: Indentation multiple (overrides default of 4)."); - Console.WriteLine(); - Console.WriteLine(" sourceFile may use wildcards like *.wxs"); - } } } diff --git a/src/wix/WixToolset.Converters/ConverterExtensionCommandLine.cs b/src/wix/WixToolset.Converters/ConverterExtensionCommandLine.cs index 06d3658c..f9facf99 100644 --- a/src/wix/WixToolset.Converters/ConverterExtensionCommandLine.cs +++ b/src/wix/WixToolset.Converters/ConverterExtensionCommandLine.cs @@ -3,7 +3,6 @@ namespace WixToolset.Converters { using System; - using System.Collections.Generic; using WixToolset.Extensibility; using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; @@ -21,11 +20,17 @@ namespace WixToolset.Converters private IServiceProvider ServiceProvider { get; } - public override IReadOnlyCollection CommandLineSwitches => new ExtensionCommandLineSwitch[] + public override CommandLineHelp GetCommandLineHelp() { - new ExtensionCommandLineSwitch { Switch = "convert", Description = "Convert v3 source code to v4 source code." }, - new ExtensionCommandLineSwitch { Switch = "format", Description = "Ensures consistent formatting of source code." }, - }; + return new CommandLineHelp("Source code converter and formatter.") + { + Commands = new[] + { + new CommandLineHelpCommand("convert", "Convert v3 source code to v4 source code."), + new CommandLineHelpCommand("format", "Ensures consistent formatting of source code."), + } + }; + } public override bool TryParseCommand(ICommandLineParser parser, string argument, out ICommandLineCommand command) { diff --git a/src/wix/WixToolset.Converters/FixupCommandBase.cs b/src/wix/WixToolset.Converters/FixupCommandBase.cs index 71d4dad7..5dc96a51 100644 --- a/src/wix/WixToolset.Converters/FixupCommandBase.cs +++ b/src/wix/WixToolset.Converters/FixupCommandBase.cs @@ -6,15 +6,17 @@ namespace WixToolset.Converters using System.Collections.Generic; using System.IO; using System.Threading; - using System.Threading.Tasks; using System.Xml; - using WixToolset.Extensibility.Data; + using WixToolset.Data; + using WixToolset.Extensibility; using WixToolset.Extensibility.Services; - internal abstract class FixupCommandBase : ICommandLineCommand + internal abstract class FixupCommandBase : BaseCommandLineCommand { - protected FixupCommandBase() + protected FixupCommandBase(IServiceProvider serviceProvider) { + this.Messaging = serviceProvider.GetService(); + this.IndentationAmount = 4; // default indentation amount this.ErrorsAsWarnings = new HashSet(); this.ExemptFiles = new HashSet(); @@ -23,11 +25,7 @@ namespace WixToolset.Converters this.SearchPatterns = new List(); } - public bool ShowHelp { get; set; } - - public bool ShowLogo { get; set; } - - public bool StopParsing { get; set; } + protected IMessaging Messaging { get; } protected CustomTableTarget CustomTableSetting { get; set; } @@ -43,15 +41,15 @@ namespace WixToolset.Converters protected bool Recurse { get; set; } - private HashSet SearchPatternResults { get; } + private HashSet SearchPatternResults { get; } - private List SearchPatterns { get; } + private List SearchPatterns { get; } private string SettingsFile1 { get; set; } private string SettingsFile2 { get; set; } - public bool TryParseArgument(ICommandLineParser parser, string argument) + public override bool TryParseArgument(ICommandLineParser parser, string argument) { if (!parser.IsSwitch(argument)) { @@ -62,14 +60,6 @@ namespace WixToolset.Converters var parameter = argument.Substring(1); switch (parameter.ToLowerInvariant()) { - case "?": - case "h": - case "-help": - this.ShowHelp = true; - this.ShowLogo = true; - this.StopParsing = true; - return true; - case "-custom-table": var customTableSetting = parser.GetNextArgumentOrError(argument); switch (customTableSetting) @@ -91,11 +81,6 @@ namespace WixToolset.Converters this.DryRun = true; return true; - case "nologo": - case "-nologo": - this.ShowLogo = false; - return true; - case "s": case "r": case "-recurse": @@ -131,8 +116,6 @@ namespace WixToolset.Converters } } - public abstract Task ExecuteAsync(CancellationToken cancellationToken); - protected void ParseSettings(string defaultSettingsFile) { // parse the settings if any were specified @@ -157,7 +140,7 @@ namespace WixToolset.Converters { if (!this.SearchPatternResults.Contains(searchPattern)) { - Console.Error.WriteLine("Could not find file \"{0}\"", searchPattern); + this.Messaging.Write(ErrorMessages.FileNotFound(null, searchPattern)); errors++; } } diff --git a/src/wix/WixToolset.Converters/FormatCommand.cs b/src/wix/WixToolset.Converters/FormatCommand.cs index 0861fc51..f3c8efdd 100644 --- a/src/wix/WixToolset.Converters/FormatCommand.cs +++ b/src/wix/WixToolset.Converters/FormatCommand.cs @@ -5,31 +5,38 @@ namespace WixToolset.Converters using System; using System.Threading; using System.Threading.Tasks; - using WixToolset.Extensibility.Services; + using WixToolset.Extensibility.Data; internal class FormatCommand : FixupCommandBase { private const string SettingsFileDefault = "wix.format.settings.xml"; - public FormatCommand(IServiceProvider serviceProvider) + public FormatCommand(IServiceProvider serviceProvider) : base(serviceProvider) { - this.Messaging = serviceProvider.GetService(); } - private IMessaging Messaging { get; } + public override CommandLineHelp GetCommandLineHelp() + { + return new CommandLineHelp("Ensures consistent formatting of source code.", "format [options] sourceFile [sourceFile ...]") + { + Switches = new[] + { + new CommandLineHelpSwitch("--dry-run", "-n", "Only display errors, do not update files."), + new CommandLineHelpSwitch("--recurse", "-r", "Search for matching files in current dir and subdirs."), + new CommandLineHelpSwitch("-set1", "Primary settings file."), + new CommandLineHelpSwitch("-set2", "Secondary settings file (overrides primary)."), + new CommandLineHelpSwitch("-indent:", "Indentation multiple (overrides default of 4)."), + }, + Notes = " sourceFile may use wildcards like *.wxs" + }; + } public override Task ExecuteAsync(CancellationToken cancellationToken) { - if (this.ShowHelp) - { - DisplayHelp(); - return Task.FromResult(-1); - } + this.ParseSettings(SettingsFileDefault); var converter = new WixConverter(this.Messaging, this.IndentationAmount, this.ErrorsAsWarnings, this.IgnoreErrors); - this.ParseSettings(SettingsFileDefault); - var errors = base.Inspect(Inspector, cancellationToken); return Task.FromResult(errors); @@ -39,22 +46,5 @@ namespace WixToolset.Converters return converter.FormatFile(file, fix); } } - - private static void DisplayHelp() - { - Console.WriteLine(); - Console.WriteLine("Usage: wix format [options] sourceFile [sourceFile ...]"); - Console.WriteLine(); - Console.WriteLine("Options:"); - Console.WriteLine(" -h|--help Show command line help."); - Console.WriteLine(" --nologo Suppress displaying the logo information."); - Console.WriteLine(" -n|--dry-run Only display errors, do not update files."); - Console.WriteLine(" -r|--recurse Search for matching files in current dir and subdirs."); - Console.WriteLine(" -set1 Primary settings file."); - Console.WriteLine(" -set2 Secondary settings file (overrides primary)."); - Console.WriteLine(" -indent: Indentation multiple (overrides default of 4)."); - Console.WriteLine(); - Console.WriteLine(" sourceFile may use wildcards like *.wxs"); - } } } diff --git a/src/wix/WixToolset.Core.Burn/BurnExtensionCommandLine.cs b/src/wix/WixToolset.Core.Burn/BurnExtensionCommandLine.cs index b306199d..f8a0b7fc 100644 --- a/src/wix/WixToolset.Core.Burn/BurnExtensionCommandLine.cs +++ b/src/wix/WixToolset.Core.Burn/BurnExtensionCommandLine.cs @@ -3,7 +3,6 @@ namespace WixToolset.Core.Burn { using System; - using System.Collections.Generic; using WixToolset.Core.Burn.CommandLine; using WixToolset.Extensibility; using WixToolset.Extensibility.Data; @@ -22,10 +21,13 @@ namespace WixToolset.Core.Burn private IServiceProvider ServiceProvider { get; } - public override IReadOnlyCollection CommandLineSwitches => new ExtensionCommandLineSwitch[] + public override CommandLineHelp GetCommandLineHelp() { - new ExtensionCommandLineSwitch { Switch = "burn", Description = "Burn specialized operations." }, - }; + return new CommandLineHelp(null) + { + Commands = new[] { new CommandLineHelpCommand("burn", "Specialized operations for manipulating Burn-based bundles.") } + }; + } public override bool TryParseCommand(ICommandLineParser parser, string argument, out ICommandLineCommand command) { diff --git a/src/wix/WixToolset.Core.Burn/CommandLine/BurnCommand.cs b/src/wix/WixToolset.Core.Burn/CommandLine/BurnCommand.cs index c9c0c657..886551e3 100644 --- a/src/wix/WixToolset.Core.Burn/CommandLine/BurnCommand.cs +++ b/src/wix/WixToolset.Core.Burn/CommandLine/BurnCommand.cs @@ -5,41 +5,50 @@ namespace WixToolset.Core.Burn.CommandLine using System; using System.Threading; using System.Threading.Tasks; + using WixToolset.Extensibility; using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; /// /// Burn specialized command. /// - internal class BurnCommand : ICommandLineCommand + internal class BurnCommand : BaseCommandLineCommand { public BurnCommand(IServiceProvider serviceProvider) { this.ServiceProvider = serviceProvider; } - public bool ShowHelp { get; set; } - - public bool ShowLogo { get; set; } - - public bool StopParsing { get; set; } - private IServiceProvider ServiceProvider { get; } private BurnSubcommandBase Subcommand { get; set; } - public Task ExecuteAsync(CancellationToken cancellationToken) + public override CommandLineHelp GetCommandLineHelp() { - if (this.ShowHelp || this.Subcommand is null) + return this.Subcommand?.GetCommandLineHelp() ?? new CommandLineHelp("Specialized operations for manipulating Burn-based bundles.", "burn detach|extract|reattach|remotepayload") { - DisplayHelp(); + Commands = new[] + { + new CommandLineHelpCommand("detach", "Detaches the burn engine from a bundle so it can be signed."), + new CommandLineHelpCommand("extract", "Extracts the internals of a bundle to a folder."), + new CommandLineHelpCommand("reattach", "Reattaches a signed burn engine to a bundle."), + new CommandLineHelpCommand("remotepayload", "Extracts the internals of a bundle."), + } + }; + } + + public override Task ExecuteAsync(CancellationToken cancellationToken) + { + if (this.Subcommand is null) + { + Console.Error.WriteLine("A subcommand is required for the \"burn\" command. Add -h to for help."); return Task.FromResult(1); } return this.Subcommand.ExecuteAsync(cancellationToken); } - public bool TryParseArgument(ICommandLineParser parser, string argument) + public override bool TryParseArgument(ICommandLineParser parser, string argument) { if (this.Subcommand is null) { @@ -67,20 +76,5 @@ namespace WixToolset.Core.Burn.CommandLine return this.Subcommand.TryParseArgument(parser, argument); } - - private static void DisplayHelp() - { - Console.WriteLine(); - Console.WriteLine("Usage: wix burn detach|reattach bundle.exe -out engine.exe"); - Console.WriteLine(); - Console.WriteLine("Options:"); - Console.WriteLine(" -h|--help Show command line help."); - Console.WriteLine(" --nologo Suppress displaying the logo information."); - Console.WriteLine(); - Console.WriteLine("Commands:"); - Console.WriteLine(); - Console.WriteLine(" detach Detaches the burn engine from a bundle so it can be signed."); - Console.WriteLine(" reattach Reattaches a signed burn engine to a bundle."); - } } } diff --git a/src/wix/WixToolset.Core.Burn/CommandLine/BurnSubcommandBase.cs b/src/wix/WixToolset.Core.Burn/CommandLine/BurnSubcommandBase.cs index cf2da708..50bb6741 100644 --- a/src/wix/WixToolset.Core.Burn/CommandLine/BurnSubcommandBase.cs +++ b/src/wix/WixToolset.Core.Burn/CommandLine/BurnSubcommandBase.cs @@ -4,10 +4,13 @@ namespace WixToolset.Core.Burn.CommandLine { using System.Threading; using System.Threading.Tasks; + using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; internal abstract class BurnSubcommandBase { + public abstract CommandLineHelp GetCommandLineHelp(); + public abstract bool TryParseArgument(ICommandLineParser parser, string argument); public abstract Task ExecuteAsync(CancellationToken cancellationToken); diff --git a/src/wix/WixToolset.Core.Burn/CommandLine/DetachSubcommand.cs b/src/wix/WixToolset.Core.Burn/CommandLine/DetachSubcommand.cs index 3f958c81..e737af0b 100644 --- a/src/wix/WixToolset.Core.Burn/CommandLine/DetachSubcommand.cs +++ b/src/wix/WixToolset.Core.Burn/CommandLine/DetachSubcommand.cs @@ -7,6 +7,7 @@ namespace WixToolset.Core.Burn.CommandLine using System.Threading; using System.Threading.Tasks; using WixToolset.Core.Burn.Inscribe; + using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; internal class DetachSubcommand : BurnSubcommandBase @@ -27,6 +28,15 @@ namespace WixToolset.Core.Burn.CommandLine private string EngineOutputPath { get; set; } + public override CommandLineHelp GetCommandLineHelp() + { + return new CommandLineHelp("Detaches the burn engine from a bundle so it can be signed.", "burn detach [options] original.exe -engine engine.exe", new[] + { + new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."), + new CommandLineHelpSwitch("-engine", "Path to extract bundle's engine file to."), + }); + } + public override Task ExecuteAsync(CancellationToken cancellationToken) { if (String.IsNullOrEmpty(this.InputPath)) diff --git a/src/wix/WixToolset.Core.Burn/CommandLine/ExtractSubcommand.cs b/src/wix/WixToolset.Core.Burn/CommandLine/ExtractSubcommand.cs index 5d6edc33..19aec14e 100644 --- a/src/wix/WixToolset.Core.Burn/CommandLine/ExtractSubcommand.cs +++ b/src/wix/WixToolset.Core.Burn/CommandLine/ExtractSubcommand.cs @@ -7,6 +7,7 @@ namespace WixToolset.Core.Burn.CommandLine using System.Threading; using System.Threading.Tasks; using WixToolset.Core.Burn.Bundles; + using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; internal class ExtractSubcommand : BurnSubcommandBase @@ -27,6 +28,15 @@ namespace WixToolset.Core.Burn.CommandLine private string ExtractPath { get; set; } + public override CommandLineHelp GetCommandLineHelp() + { + return new CommandLineHelp("Extracts the internals of a bundle to a folder.", "burn extract [options] bundle.exe -o outputfolder ", new[] + { + new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."), + new CommandLineHelpSwitch("-out", "-o", "Folder to extract the bundle contents to."), + }); + } + public override Task ExecuteAsync(CancellationToken cancellationToken) { if (String.IsNullOrEmpty(this.InputPath)) @@ -77,6 +87,7 @@ namespace WixToolset.Core.Burn.CommandLine return true; case "o": + case "out": this.ExtractPath = parser.GetNextArgumentAsDirectoryOrError(argument); return true; } diff --git a/src/wix/WixToolset.Core.Burn/CommandLine/ReattachSubcommand.cs b/src/wix/WixToolset.Core.Burn/CommandLine/ReattachSubcommand.cs index ba034973..da6cd9b4 100644 --- a/src/wix/WixToolset.Core.Burn/CommandLine/ReattachSubcommand.cs +++ b/src/wix/WixToolset.Core.Burn/CommandLine/ReattachSubcommand.cs @@ -7,6 +7,7 @@ namespace WixToolset.Core.Burn.CommandLine using System.Threading; using System.Threading.Tasks; using WixToolset.Core.Burn.Inscribe; + using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; internal class ReattachSubcommand : BurnSubcommandBase @@ -29,6 +30,15 @@ namespace WixToolset.Core.Burn.CommandLine private string OutputPath { get; set; } + public override CommandLineHelp GetCommandLineHelp() + { + return new CommandLineHelp("Reattaches a signed burn engine to a bundle.", "burn reattach [options] original.exe signed.exe -o final.exe", new[] + { + new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."), + new CommandLineHelpSwitch("-out", "-o", "Output bundle with signed engine attached."), + }); + } + public override Task ExecuteAsync(CancellationToken cancellationToken) { if (String.IsNullOrEmpty(this.InputPath)) diff --git a/src/wix/WixToolset.Core.Burn/CommandLine/RemotePayloadSubcommand.cs b/src/wix/WixToolset.Core.Burn/CommandLine/RemotePayloadSubcommand.cs index d152504d..ae98ccca 100644 --- a/src/wix/WixToolset.Core.Burn/CommandLine/RemotePayloadSubcommand.cs +++ b/src/wix/WixToolset.Core.Burn/CommandLine/RemotePayloadSubcommand.cs @@ -15,6 +15,7 @@ namespace WixToolset.Core.Burn.CommandLine using WixToolset.Data; using WixToolset.Data.Symbols; using WixToolset.Extensibility; + using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; internal class RemotePayloadSubcommand : BurnSubcommandBase @@ -66,6 +67,36 @@ namespace WixToolset.Core.Burn.CommandLine private bool UseCertificate { get; set; } + public override CommandLineHelp GetCommandLineHelp() + { + return new CommandLineHelp("Generate source code for a remote payload", "burn remotepayload [options] payloadfile [payloadfile ...]", new[] + { + new CommandLineHelpSwitch("-basepath", "-bp", "Folder as base to make payloads relative."), + new CommandLineHelpSwitch("-bundlepayloadgeneration", "Sets the package payload generation option; see the Payload Generation Types below."), + new CommandLineHelpSwitch("-downloadurl", "-du", "Set the DownloadUrl attribute on the generated payloads."), + new CommandLineHelpSwitch("-out", "-o", "Path to output the source code file."), + new CommandLineHelpSwitch("-recurse", "-r", "Indicates to add all payloads in directory recursively."), + new CommandLineHelpSwitch("-intermediatefolder", "Optional working folder. If not specified %TMP% folder will be created."), + new CommandLineHelpSwitch("-packagetype", "Explicitly set package type; see the Pacakge Types below."), + new CommandLineHelpSwitch("-usecertificate", "Use certificate to validate signed payloads. This option is not recommended."), + }) + { + Notes = String.Join(Environment.NewLine, + "Payload Generation Types:", + " none", + " externalwithoutdownloadurl", + " external", + " all", + String.Empty, + "Package Types:", + " bundle", + " exe", + " msi", + " msp", + " msu") + }; + } + public override Task ExecuteAsync(CancellationToken cancellationToken) { var inputPaths = this.ExpandInputPaths(); diff --git a/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManagerCommand.cs b/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManagerCommand.cs index 008fcebd..f7a93a6d 100644 --- a/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManagerCommand.cs +++ b/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManagerCommand.cs @@ -7,13 +7,14 @@ namespace WixToolset.Core.ExtensionCache using System.Linq; using System.Threading; using System.Threading.Tasks; + using WixToolset.Extensibility; using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; /// /// Extension cache manager command. /// - internal class ExtensionCacheManagerCommand : ICommandLineCommand + internal class ExtensionCacheManagerCommand : BaseCommandLineCommand { private enum CacheSubcommand { @@ -29,12 +30,6 @@ namespace WixToolset.Core.ExtensionCache this.ExtensionReferences = new List(); } - public bool ShowHelp { get; set; } - - public bool ShowLogo { get; set; } - - public bool StopParsing { get; set; } - private IMessaging Messaging { get; } private IExtensionManager ExtensionManager { get; } @@ -45,12 +40,30 @@ namespace WixToolset.Core.ExtensionCache private List ExtensionReferences { get; } - public async Task ExecuteAsync(CancellationToken cancellationToken) + public override CommandLineHelp GetCommandLineHelp() + { + return new CommandLineHelp("Manage the extension cache.", "extension add|remove|list [options] [extensionRef]") + { + Switches = new[] + { + new CommandLineHelpSwitch("--global", "-g", "Add/remove the extension for the current user."), + }, + Commands = new[] + { + new CommandLineHelpCommand("add", "Add extension to the cache."), + new CommandLineHelpCommand("list", "List extensions in the cache."), + new CommandLineHelpCommand("remove", "Remove extension from the cache."), + }, + Notes = " extensionRef format: extensionId/version (the version is optional)" + }; + } + + public override async Task ExecuteAsync(CancellationToken cancellationToken) { - if (this.ShowHelp || !this.Subcommand.HasValue) + if (!this.Subcommand.HasValue) { - DisplayHelp(); - return 1; + Console.Error.WriteLine("A subcommand is required for the \"extension\" command. Use -h to for help."); + return -1; } var success = false; @@ -74,7 +87,7 @@ namespace WixToolset.Core.ExtensionCache return success ? 0 : 2; } - public bool TryParseArgument(ICommandLineParser parser, string argument) + public override bool TryParseArgument(ICommandLineParser parser, string argument) { if (!parser.IsSwitch(argument)) { @@ -98,19 +111,6 @@ namespace WixToolset.Core.ExtensionCache var parameter = argument.Substring(1); switch (parameter.ToLowerInvariant()) { - case "?": - case "h": - case "-help": - this.ShowHelp = true; - this.ShowLogo = true; - this.StopParsing = true; - return true; - - case "nologo": - case "-nologo": - this.ShowLogo = false; - return true; - case "g": case "-global": this.Global = true; @@ -161,24 +161,5 @@ namespace WixToolset.Core.ExtensionCache return found; } - - private static void DisplayHelp() - { - Console.WriteLine(); - Console.WriteLine("Usage: wix extension add|remove|list [extensionRef]"); - Console.WriteLine(); - Console.WriteLine("Options:"); - Console.WriteLine(" -h|--help Show command line help."); - Console.WriteLine(" -g|--global Add/remove the extension for the current user."); - Console.WriteLine(" --nologo Suppress displaying the logo information."); - Console.WriteLine(); - Console.WriteLine("Commands:"); - Console.WriteLine(); - Console.WriteLine(" add Add extension to the cache."); - Console.WriteLine(" list List extensions in the cache."); - Console.WriteLine(" remove Remove extension from the cache."); - Console.WriteLine(); - Console.WriteLine(" extensionRef format: extensionId/version (the version is optional)"); - } } } diff --git a/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManagerExtensionCommandLine.cs b/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManagerExtensionCommandLine.cs index 2a603adf..788b986c 100644 --- a/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManagerExtensionCommandLine.cs +++ b/src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManagerExtensionCommandLine.cs @@ -3,7 +3,6 @@ namespace WixToolset.Core.ExtensionCache { using System; - using System.Collections.Generic; using WixToolset.Extensibility; using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; @@ -21,10 +20,13 @@ namespace WixToolset.Core.ExtensionCache private IServiceProvider ServiceProvider { get; } - public override IReadOnlyCollection CommandLineSwitches => new ExtensionCommandLineSwitch[] + public override CommandLineHelp GetCommandLineHelp() { - new ExtensionCommandLineSwitch { Switch = "extension", Description = "Manage extension cache." }, - }; + return new CommandLineHelp("Manage the extension cache.") + { + Commands = new[] { new CommandLineHelpCommand("extension", "Manage extension cache.") } + }; + } public override bool TryParseCommand(ICommandLineParser parser, string argument, out ICommandLineCommand command) { diff --git a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/DecompilerSubcommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/DecompilerSubcommand.cs index 0f806c95..97da7a9e 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/DecompilerSubcommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/DecompilerSubcommand.cs @@ -42,6 +42,22 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine private bool SuppressUI { get; set; } + public override CommandLineHelp GetCommandLineHelp() + { + return new CommandLineHelp("Converts a Windows Installer database back into source code.", "msi decompile [options] inputfile", new[] + { + new CommandLineHelpSwitch("-cub", "Optional path to a custom validation .CUBe file."), + new CommandLineHelpSwitch("-sct", "Suppress decompiling custom tables."), + new CommandLineHelpSwitch("-sdet", "Suppress dropping empty tables."), + new CommandLineHelpSwitch("-sras", "Suppress relative action sequencing."), + new CommandLineHelpSwitch("-sui", "Suppress decompiling UI tables."), + new CommandLineHelpSwitch("-type", "Optional specify the input file type: msi or msm. If not specified, type will be inferred by file extension."), + new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."), + new CommandLineHelpSwitch("-out", "-o", "Path to output the decompiled .wxs file. If not specified, outputs next to inputfile"), + new CommandLineHelpSwitch("-x", "Folder to export embedded binaries and icons to."), + }); + } + public override Task ExecuteAsync(CancellationToken cancellationToken) { if (String.IsNullOrEmpty(this.InputPath)) diff --git a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/InscribeSubcommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/InscribeSubcommand.cs index ebc4673d..dd80b8e2 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/InscribeSubcommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/InscribeSubcommand.cs @@ -7,6 +7,7 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine using System.Threading; using System.Threading.Tasks; using WixToolset.Core.WindowsInstaller.Inscribe; + using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; internal class InscribeSubcommand : WindowsInstallerSubcommandBase @@ -27,6 +28,15 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine private string OutputPath { get; set; } + public override CommandLineHelp GetCommandLineHelp() + { + return new CommandLineHelp("Updates MSI database with cabinet signature information.", "msi inscribe [options] input.msi [-out inscribed.msi]", new[] + { + new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."), + new CommandLineHelpSwitch("-out", "-o", "Path to output the inscribed MSI. If not provided, the input MSI is updated in place."), + }); + } + public override Task ExecuteAsync(CancellationToken cancellationToken) { if (String.IsNullOrEmpty(this.InputPath)) diff --git a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/TransformSubcommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/TransformSubcommand.cs index 7ed41d1a..77f29723 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/TransformSubcommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/TransformSubcommand.cs @@ -12,6 +12,7 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine using WixToolset.Data.Symbols; using WixToolset.Data.WindowsInstaller; using WixToolset.Extensibility; + using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; internal class TransformSubcommand : WindowsInstallerSubcommandBase @@ -51,6 +52,52 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine private TransformFlags ValidationFlags { get; set; } + public override CommandLineHelp GetCommandLineHelp() + { + return new CommandLineHelp("Creates an MST transform file.", "msi transform [options] target.msi [updated.msi] -out output.mst") + { + Switches = new[] + { + new CommandLineHelpSwitch("-a", "Admin image, generates source file information in the transform."), + new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."), + new CommandLineHelpSwitch("-p", "Preserve unchanged rows."), + new CommandLineHelpSwitch("-pedantic", "Show pedantic messages."), + new CommandLineHelpSwitch("-serr ", "Suppress error when applying transform; see Error flags below"), + new CommandLineHelpSwitch("-t ", "Use default validation flags for the transform type; see Transform types below"), + new CommandLineHelpSwitch("-val ", "Validation flags for the transform; see Validation flags below"), + new CommandLineHelpSwitch("-x", "Folder to extract binaries."), + new CommandLineHelpSwitch("-xo", "Output transfrom as a WiX output instead of an MST file."), + new CommandLineHelpSwitch("-out", "-o", "Path to output the transform file."), + }, + Notes = String.Join(Environment.NewLine, + "Error flags:", + " a Ignore errors when adding an existing row", + " b Ignore errors when deleting a missing row", + " c Ignore errors when adding an existing table", + " d Ignore errors when deleting a missing table", + " e Ignore errors when modifying a missing row", + " f Ignore errors when changing the code page", + String.Empty, + "Validation flags:", + " g UpgradeCode must match", + " l Language must match", + " r Product ID must match", + " s Check major version only", + " t Check major and minor versions", + " u Check major, minor, and upgrade versions", + " v Upgrade version < target version", + " w Upgrade version <= target version", + " x Upgrade version = target version", + " y Upgrade version > target version", + " z Upgrade version >= target version", + String.Empty, + "Transform types:", + " language Default flags for a language transform", + " instance Default flags for an instance transform", + " patch Default flags for a patch transform") + }; + } + public override Task ExecuteAsync(CancellationToken cancellationToken) { if (String.IsNullOrEmpty(this.TargetPath)) diff --git a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs index eb014086..f00002e3 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs @@ -9,6 +9,7 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine using System.Threading.Tasks; using WixToolset.Core.WindowsInstaller.Validate; using WixToolset.Data.WindowsInstaller; + using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; internal class ValidateSubcommand : WindowsInstallerSubcommandBase @@ -35,6 +36,18 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine private List SuppressIces { get; } = new List(); + public override CommandLineHelp GetCommandLineHelp() + { + return new CommandLineHelp("Validates MSI database using standard or custom ICEs.", "msi validate [options] inputfile", new[] + { + new CommandLineHelpSwitch("-cub", "Optional path to a custom validation .CUBe file."), + new CommandLineHelpSwitch("-ice", "Validates only with the specified ICE. May be provided multiple times."), + new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."), + new CommandLineHelpSwitch("-pdb", "Optional path to .wixpdb for source line information. If not provided, will check next to the input file."), + new CommandLineHelpSwitch("-sice", "Suppresses an ICE validator."), + }); + } + public override Task ExecuteAsync(CancellationToken cancellationToken) { WindowsInstallerData data = null; diff --git a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerCommand.cs b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerCommand.cs index f11020c8..964aab71 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerCommand.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerCommand.cs @@ -5,41 +5,50 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine using System; using System.Threading; using System.Threading.Tasks; + using WixToolset.Extensibility; using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; /// /// Windows Installer specialized command. /// - internal class WindowsInstallerCommand : ICommandLineCommand + internal class WindowsInstallerCommand : BaseCommandLineCommand { public WindowsInstallerCommand(IServiceProvider serviceProvider) { this.ServiceProvider = serviceProvider; } - public bool ShowHelp { get; set; } - - public bool ShowLogo { get; set; } - - public bool StopParsing { get; set; } - private IServiceProvider ServiceProvider { get; } private WindowsInstallerSubcommandBase Subcommand { get; set; } - public Task ExecuteAsync(CancellationToken cancellationToken) + public override CommandLineHelp GetCommandLineHelp() { - if (this.ShowHelp || this.Subcommand is null) + return this.Subcommand?.GetCommandLineHelp() ?? new CommandLineHelp("Specialized operations for manipulating Windows Installer databases.", "msi decompile|inscribe|transform|validate") { - DisplayHelp(); + Commands = new[] + { + new CommandLineHelpCommand("decompile", "Converts a Windows Installer database back into source code."), + new CommandLineHelpCommand("inscribe", "Updates MSI database with cabinet signature information."), + new CommandLineHelpCommand("transform", "Creates an MST transform file."), + new CommandLineHelpCommand("validate", "Validates MSI database using standard or custom ICEs."), + } + }; + } + + public override Task ExecuteAsync(CancellationToken cancellationToken) + { + if (this.Subcommand is null) + { + Console.Error.WriteLine("A subcommand is required for the \"msi\" command. Add -h to for help."); return Task.FromResult(1); } return this.Subcommand.ExecuteAsync(cancellationToken); } - public bool TryParseArgument(ICommandLineParser parser, string argument) + public override bool TryParseArgument(ICommandLineParser parser, string argument) { if (this.Subcommand is null) { @@ -67,21 +76,5 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine return this.Subcommand.TryParseArgument(parser, argument); } - - private static void DisplayHelp() - { - Console.WriteLine(); - Console.WriteLine("Usage: wix msi inscribe input.msi [-intermedidateFolder folder] [-out output.msi]"); - Console.WriteLine(); - Console.WriteLine("Options:"); - Console.WriteLine(" -h|--help Show command line help."); - Console.WriteLine(" --nologo Suppress displaying the logo information."); - Console.WriteLine(); - Console.WriteLine("Commands:"); - Console.WriteLine(); - Console.WriteLine(" inscribe Updates MSI database with cabinet signature information."); - Console.WriteLine(" transform Creates an MST transform file."); - Console.WriteLine(" validate Validates MSI database using standard or custom ICEs."); - } } } diff --git a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerSubcommandBase.cs b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerSubcommandBase.cs index e3f26296..cbe389e2 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerSubcommandBase.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerSubcommandBase.cs @@ -4,10 +4,13 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine { using System.Threading; using System.Threading.Tasks; + using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; internal abstract class WindowsInstallerSubcommandBase { + public abstract CommandLineHelp GetCommandLineHelp(); + public abstract bool TryParseArgument(ICommandLineParser parser, string argument); public abstract Task ExecuteAsync(CancellationToken cancellationToken); diff --git a/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerExtensionCommandLine.cs b/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerExtensionCommandLine.cs index ae8f0a94..2919451c 100644 --- a/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerExtensionCommandLine.cs +++ b/src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerExtensionCommandLine.cs @@ -3,7 +3,6 @@ namespace WixToolset.Core.WindowsInstaller { using System; - using System.Collections.Generic; using WixToolset.Core.WindowsInstaller.CommandLine; using WixToolset.Extensibility; using WixToolset.Extensibility.Data; @@ -22,10 +21,16 @@ namespace WixToolset.Core.WindowsInstaller private IServiceProvider ServiceProvider { get; } - public override IReadOnlyCollection CommandLineSwitches => new ExtensionCommandLineSwitch[] + public override CommandLineHelp GetCommandLineHelp() { - new ExtensionCommandLineSwitch { Switch = "msi", Description = "Windows Installer specialized operations." }, - }; + return new CommandLineHelp("Specialized operations for manipulating Windows Installer databases.") + { + Commands = new[] + { + new CommandLineHelpCommand("msi", "Windows Installer specialized operations."), + } + }; + } public override bool TryParseCommand(ICommandLineParser parser, string argument, out ICommandLineCommand command) { diff --git a/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs b/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs index a00b4b12..51101d01 100644 --- a/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs +++ b/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs @@ -14,7 +14,7 @@ namespace WixToolset.Core.CommandLine using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; - internal class BuildCommand : ICommandLineCommand + internal class BuildCommand : BaseCommandLineCommand { private readonly CommandLine commandLine; @@ -26,21 +26,6 @@ namespace WixToolset.Core.CommandLine this.commandLine = new CommandLine(this.ServiceProvider, this.Messaging); } - public bool ShowHelp - { - get { return this.commandLine.ShowHelp; } - set { this.commandLine.ShowHelp = value; } - } - - public bool ShowLogo - { - get { return this.commandLine.ShowLogo; } - set { this.commandLine.ShowLogo = value; } - } - - // Stop parsing when we've decided to show help. - public bool StopParsing => this.commandLine.ShowHelp; - private IServiceProvider ServiceProvider { get; } private IMessaging Messaging { get; } @@ -57,14 +42,40 @@ namespace WixToolset.Core.CommandLine private string TrackingFile { get; set; } - public Task ExecuteAsync(CancellationToken cancellationToken) + public override CommandLineHelp GetCommandLineHelp() { - if (this.commandLine.ShowHelp) + return new CommandLineHelp("", "build [options] sourcevile [sourcefile ...] -out output.ext", new[] { - Console.WriteLine("TODO: Show build command help"); - return Task.FromResult(-1); - } + new CommandLineHelpSwitch("-arch", "Set the architecture of the output."), + new CommandLineHelpSwitch("-bindfiles", "-bf", "Bind files into an output .wixlib. Ignored if not building a .wixlib."), + new CommandLineHelpSwitch("-bindpath", "Bind path to search for content files."), + new CommandLineHelpSwitch("-cabcache", "-cc", "Set a folder to cache cabinets across builds."), + new CommandLineHelpSwitch("-culture", "Adds a culture to filter localization files."), + new CommandLineHelpSwitch("-define", "-d", "Sets a preprocessor variable."), + new CommandLineHelpSwitch("-defaultcompressionlevel", "-dcl", "Default compression level; see Compression levels below."), + new CommandLineHelpSwitch("-include", "-i", "Folder to search for include files."), + new CommandLineHelpSwitch("-intermediatefolder", "Optional working folder. If not specified a folder in %TMP% will be created."), + new CommandLineHelpSwitch("-loc", "Localization file to use in the build. By default, .wxl files are recognized as localization."), + new CommandLineHelpSwitch("-lib", "Library file to use in the build. By default, .wixlb files are recognized as libraries."), + new CommandLineHelpSwitch("-src", "Source file to use in the build. By default, .wxs files are recognized as source code."), + new CommandLineHelpSwitch("-out", "-o", "Path to output the build to."), + new CommandLineHelpSwitch("-outputtype", "Explicitly set the output type if it cannot be determined from the output."), + new CommandLineHelpSwitch("-pdb", "Optional path to output .wixpdb. Default will write .wixpdb beside output path."), + new CommandLineHelpSwitch("-pdbtype", "Switch to disable creation of .wixpdb. Types: full or none."), + }) + { + Notes = String.Join(Environment.NewLine, + "Compression levels:", + " none Use no compression", + " low Use low compression", + " medium Use medium compression", + " high Use high compression", + " mszip Use ms-zip compression") + }; + } + public override Task ExecuteAsync(CancellationToken cancellationToken) + { this.IntermediateFolder = this.commandLine.CalculateIntermedateFolder(); this.Platform = this.commandLine.Platform; @@ -144,7 +155,7 @@ namespace WixToolset.Core.CommandLine return Task.FromResult(this.Messaging.LastErrorNumber); } - public bool TryParseArgument(ICommandLineParser parser, string argument) + public override bool TryParseArgument(ICommandLineParser parser, string argument) { return this.commandLine.TryParseArgument(argument, parser); } @@ -465,7 +476,7 @@ namespace WixToolset.Core.CommandLine public List SourceFilePaths { get; } = new List(); - public List UnevaluatedInputFilePaths { get; } = new List(); + public List UnclassifiedInputFilePaths { get; } = new List(); public Platform Platform { get; private set; } @@ -473,10 +484,6 @@ namespace WixToolset.Core.CommandLine public PdbType PdbType { get; private set; } - public bool ShowLogo { get; set; } - - public bool ShowHelp { get; set; } - public string IntermediateFolder { get; private set; } public string OutputFile { get; private set; } @@ -535,6 +542,7 @@ namespace WixToolset.Core.CommandLine } case "cc": + case "cabcache": this.CabCachePath = parser.GetNextArgumentOrError(arg); return true; @@ -617,7 +625,7 @@ namespace WixToolset.Core.CommandLine } else { - parser.GetArgumentAsFilePathOrError(arg, "input file", this.UnevaluatedInputFilePaths); + parser.GetArgumentAsFilePathOrError(arg, "input file", this.UnclassifiedInputFilePaths); return true; } } @@ -737,7 +745,7 @@ namespace WixToolset.Core.CommandLine var outputPath = this.OutputFile; var outputType = this.CalculateOutputType(); - foreach (var path in this.UnevaluatedInputFilePaths) + foreach (var path in this.UnclassifiedInputFilePaths) { var extension = Path.GetExtension(path); diff --git a/src/wix/WixToolset.Core/CommandLine/CommandLine.cs b/src/wix/WixToolset.Core/CommandLine/CommandLine.cs index 07dcc2d2..bbe985f8 100644 --- a/src/wix/WixToolset.Core/CommandLine/CommandLine.cs +++ b/src/wix/WixToolset.Core/CommandLine/CommandLine.cs @@ -21,6 +21,10 @@ namespace WixToolset.Core.CommandLine private IMessaging Messaging { get; } + private bool ShowHelp { get; set; } + + private bool SuppressLogo { get; set; } + public ICommandLineCommand CreateCommand(string[] args) { var arguments = this.ServiceProvider.GetService(); @@ -49,11 +53,12 @@ namespace WixToolset.Core.CommandLine var command = this.Parse(context); - if (command.ShowLogo) + if (!this.SuppressLogo && command?.ShowLogo == true) { var branding = this.ServiceProvider.GetService(); Console.WriteLine(branding.ReplacePlaceholders("[AssemblyProduct] [AssemblyDescription] version [ProductVersion]")); Console.WriteLine(branding.ReplacePlaceholders("[AssemblyCopyright]")); + Console.WriteLine(); } return command; @@ -71,7 +76,6 @@ namespace WixToolset.Core.CommandLine private ICommandLineCommand Parse(ICommandLineContext context) { - var branding = context.ServiceProvider.GetService(); var extensions = context.ExtensionManager.GetServices(); foreach (var extension in extensions) @@ -86,28 +90,31 @@ namespace WixToolset.Core.CommandLine String.IsNullOrEmpty(parser.ErrorArgument) && parser.TryGetNextSwitchOrArgument(out var arg)) { - if (String.IsNullOrWhiteSpace(arg)) // skip blank arguments. - { - continue; - } - - // First argument must be the command or global switch (that creates a command). + // If we don't have a command yet, try to parse for a command or a global switch. if (command == null) { - if (!this.TryParseCommand(arg, parser, extensions, out command)) + if (this.TryParseCommand(arg, parser, extensions, out command)) { + // Found our command, all good. + } + else if (!parser.IsSwitch(arg) || !TryParseCommandLineArgumentWithExtension(arg, parser, extensions)) + { + // Not a global switch handled by an extension, so failure. parser.ReportErrorArgument(arg); } } else if (parser.IsSwitch(arg)) { - if (!command.TryParseArgument(parser, arg) && !TryParseCommandLineArgumentWithExtension(arg, parser, extensions) && - !this.TryParseStandardCommandLineSwitch(command, parser, arg)) + // Commands get first crack at parsing switches then extensions then the standard. + if (!command.TryParseArgument(parser, arg) && + !TryParseCommandLineArgumentWithExtension(arg, parser, extensions) && + !this.TryParseStandardCommandLineSwitch(parser, arg)) { parser.ReportErrorArgument(arg); } } - else if (!TryParseCommandLineArgumentWithExtension(arg, parser, extensions) && !command.TryParseArgument(parser, arg)) + else if (!TryParseCommandLineArgumentWithExtension(arg, parser, extensions) && + !command.TryParseArgument(parser, arg)) { parser.ReportErrorArgument(arg); } @@ -121,10 +128,15 @@ namespace WixToolset.Core.CommandLine // If we hit an error, do not return a command. if (!String.IsNullOrEmpty(parser.ErrorArgument)) { - return null; + command = null; + } + else if (this.ShowHelp || command == null) + { + var branding = context.ServiceProvider.GetService(); + command = new HelpCommand(extensions, branding, command); } - return command ?? new HelpCommand(extensions, branding); + return command; } private bool TryParseCommand(string arg, ICommandLineParser parser, IEnumerable extensions, out ICommandLineCommand command) @@ -141,7 +153,7 @@ namespace WixToolset.Core.CommandLine case "help": case "-help": var branding = this.ServiceProvider.GetService(); - command = new HelpCommand(extensions, branding); + command = new HelpCommand(extensions, branding, null); break; case "version": @@ -184,7 +196,7 @@ namespace WixToolset.Core.CommandLine return false; } - private bool TryParseStandardCommandLineSwitch(ICommandLineCommand command, ICommandLineParser parser, string arg) + private bool TryParseStandardCommandLineSwitch(ICommandLineParser parser, string arg) { var parameter = arg.Substring(1).ToLowerInvariant(); @@ -193,11 +205,13 @@ namespace WixToolset.Core.CommandLine case "?": case "h": case "help": - command.ShowHelp = true; + case "-help": + this.ShowHelp = true; return true; case "nologo": - command.ShowLogo = false; + case "-nologo": + this.SuppressLogo = true; return true; case "v": diff --git a/src/wix/WixToolset.Core/CommandLine/CommandLineParser.cs b/src/wix/WixToolset.Core/CommandLine/CommandLineParser.cs index 7e6e7cac..52350929 100644 --- a/src/wix/WixToolset.Core/CommandLine/CommandLineParser.cs +++ b/src/wix/WixToolset.Core/CommandLine/CommandLineParser.cs @@ -5,6 +5,7 @@ namespace WixToolset.Core.CommandLine using System; using System.Collections.Generic; using System.IO; + using System.Linq; using WixToolset.Data; using WixToolset.Extensibility.Services; @@ -12,19 +13,19 @@ namespace WixToolset.Core.CommandLine { private const string ExpectedArgument = "expected argument"; - public string ErrorArgument { get; private set; } - - private Queue RemainingArguments { get; } - - private IMessaging Messaging { get; } - public CommandLineParser(IMessaging messaging, string[] arguments, string errorArgument) { this.Messaging = messaging; - this.RemainingArguments = new Queue(arguments); + this.RemainingArguments = new Queue(arguments.Where(a => !String.IsNullOrWhiteSpace(a))); // skip blank arguments. this.ErrorArgument = errorArgument; } + public string ErrorArgument { get; private set; } + + private Queue RemainingArguments { get; } + + private IMessaging Messaging { get; } + public bool IsSwitch(string arg) { return !String.IsNullOrEmpty(arg) && '-' == arg[0]; @@ -132,15 +133,15 @@ namespace WixToolset.Core.CommandLine this.ErrorArgument = argument; } - public bool TryGetNextSwitchOrArgument(out string arg) + public bool TryGetNextSwitchOrArgument(out string argument) { if (this.RemainingArguments.Count > 0) { - arg = this.RemainingArguments.Dequeue(); + argument = this.RemainingArguments.Dequeue(); return true; } - arg = null; + argument = null; return false; } diff --git a/src/wix/WixToolset.Core/CommandLine/HelpCommand.cs b/src/wix/WixToolset.Core/CommandLine/HelpCommand.cs index 9a879cc8..f6d3d776 100644 --- a/src/wix/WixToolset.Core/CommandLine/HelpCommand.cs +++ b/src/wix/WixToolset.Core/CommandLine/HelpCommand.cs @@ -11,67 +11,115 @@ namespace WixToolset.Core.CommandLine using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; - internal class HelpCommand : ICommandLineCommand + internal class HelpCommand : BaseCommandLineCommand { - private static readonly ExtensionCommandLineSwitch[] BuiltInSwitches = new ExtensionCommandLineSwitch[] - { - new ExtensionCommandLineSwitch { Switch = "build", Description = "Build a wixlib, package or bundle." }, - new ExtensionCommandLineSwitch { Switch = "decompile", Description = "Decompile a package or bundle into source code." }, - }; - - public HelpCommand(IEnumerable extensions, IWixBranding branding) + public HelpCommand(IEnumerable extensions, IWixBranding branding, ICommandLineCommand command) { this.Extensions = extensions; this.Branding = branding; + this.Command = command; } - public bool ShowHelp + public override bool ShowLogo => true; + + private IEnumerable Extensions { get; } + + private IWixBranding Branding { get; } + + private ICommandLineCommand Command { get; } + + public override CommandLineHelp GetCommandLineHelp() { - get => true; - set { } + return new CommandLineHelp(null, "[command] [options]") + { + Switches = new[] + { + new CommandLineHelpSwitch("--help", "-h", "Show command line help."), + new CommandLineHelpSwitch("--version", "-v", "Display WiX Toolset version in use."), + new CommandLineHelpSwitch("--nologo", "Suppress displaying the logo information."), + }, + Commands = new[] + { + new CommandLineHelpCommand("build", "Build a wixlib, package or bundle.") + }, + Notes = "Run 'wix [command] -h' for more information on a command." + }; } - public bool ShowLogo + public override Task ExecuteAsync(CancellationToken _) { - get => true; - set { } - } + var extensionsHelp = this.Extensions.Select(e => e.GetCommandLineHelp()).Where(h => h != null).ToList(); - public bool StopParsing => true; + var help = this.Command?.GetCommandLineHelp() ?? this.GetCommandLineHelp(); - private IEnumerable Extensions { get; } + var switches = new List(); + if (help.Switches != null) + { + switches.AddRange(help.Switches); + } - private IWixBranding Branding { get; } + switches.AddRange(extensionsHelp.Where(e => e.Switches != null).SelectMany(e => e.Switches)); - public Task ExecuteAsync(CancellationToken _) - { - var commandLineSwitches = new List(BuiltInSwitches); - commandLineSwitches.AddRange(this.Extensions.SelectMany(e => e.CommandLineSwitches).OrderBy(s => s.Switch, StringComparer.Ordinal)); - - Console.WriteLine(); - Console.WriteLine("Usage: wix [option]"); - Console.WriteLine("Usage: wix [command]"); - Console.WriteLine(); - Console.WriteLine("Options:"); - Console.WriteLine(" -h|--help Show command line help."); - Console.WriteLine(" --version Display WiX Toolset version in use."); - Console.WriteLine(); - - Console.WriteLine("Commands:"); - foreach (var commandLineSwitch in commandLineSwitches) + var commands = new List(); + if (help.Commands != null) + { + commands.AddRange(help.Commands); + } + + if (this.Command == null) + { + commands.AddRange(extensionsHelp.Where(e => e.Commands != null).SelectMany(e => e.Commands)); + } + + if (!String.IsNullOrEmpty(help.Description)) + { + Console.WriteLine("Description:"); + Console.WriteLine(" {0}", help.Description); + Console.WriteLine(); + } + + if (!String.IsNullOrEmpty(help.Usage)) + { + Console.WriteLine("Usage:"); + Console.WriteLine(" wix {0}", help.Usage); + Console.WriteLine(); + } + + if (switches.Count > 0) + { + Console.WriteLine("Options:"); + foreach (var commandLineSwitch in help.Switches) + { + var switchName = String.IsNullOrEmpty(commandLineSwitch.ShortName) ? commandLineSwitch.Name : $"{commandLineSwitch.ShortName}|{commandLineSwitch.Name}"; + Console.WriteLine(" {0,-17} {1}", switchName, commandLineSwitch.Description); + } + + Console.WriteLine(); + } + + if (commands.Count > 0) + { + Console.WriteLine("Commands:"); + foreach (var command in commands) + { + Console.WriteLine(" {0,-17} {1}", command.Name, command.Description); + } + + Console.WriteLine(); + } + + if (!String.IsNullOrEmpty(help.Notes)) { - Console.WriteLine(" {0,-17} {1}", commandLineSwitch.Switch, commandLineSwitch.Description); + Console.WriteLine(help.Notes); + Console.WriteLine(); } - Console.WriteLine(); - Console.WriteLine("Run 'wix [command] -h[elp]' for more information on a command."); - Console.WriteLine(); Console.WriteLine(this.Branding.ReplacePlaceholders("For more information see: [SupportUrl]")); return Task.FromResult(-1); } - public bool TryParseArgument(ICommandLineParser parseHelper, string argument) + public override bool TryParseArgument(ICommandLineParser parseHelper, string argument) { return true; // eat any arguments } diff --git a/src/wix/WixToolset.Core/CommandLine/VersionCommand.cs b/src/wix/WixToolset.Core/CommandLine/VersionCommand.cs index 7e08b66e..2fb13967 100644 --- a/src/wix/WixToolset.Core/CommandLine/VersionCommand.cs +++ b/src/wix/WixToolset.Core/CommandLine/VersionCommand.cs @@ -5,18 +5,18 @@ namespace WixToolset.Core.CommandLine using System; using System.Threading; using System.Threading.Tasks; + using WixToolset.Extensibility; using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; - internal class VersionCommand : ICommandLineCommand + internal class VersionCommand : BaseCommandLineCommand { - public bool ShowHelp { get; set; } - - public bool ShowLogo { get; set; } - - public bool StopParsing => true; + public override CommandLineHelp GetCommandLineHelp() + { + return null; + } - public Task ExecuteAsync(CancellationToken cancellationToken) + public override Task ExecuteAsync(CancellationToken cancellationToken) { // $(GitBaseVersionMajor).$(GitBaseVersionMinor).$(GitBaseVersionPatch)$(GitSemVerDashLabel)+$(Commit) Console.WriteLine("{0}.{1}.{2}{3}+{4}", ThisAssembly.Git.BaseVersion.Major @@ -27,7 +27,7 @@ namespace WixToolset.Core.CommandLine return Task.FromResult(0); } - public bool TryParseArgument(ICommandLineParser parseHelper, string argument) + public override bool TryParseArgument(ICommandLineParser parseHelper, string argument) { return true; // eat any arguments } diff --git a/src/wix/test/Example.Extension/ExamplePreprocessorExtensionAndCommandLine.cs b/src/wix/test/Example.Extension/ExamplePreprocessorExtensionAndCommandLine.cs index 7244798a..37834826 100644 --- a/src/wix/test/Example.Extension/ExamplePreprocessorExtensionAndCommandLine.cs +++ b/src/wix/test/Example.Extension/ExamplePreprocessorExtensionAndCommandLine.cs @@ -3,7 +3,6 @@ namespace Example.Extension { using System; - using System.Collections.Generic; using WixToolset.Extensibility; using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; @@ -12,7 +11,13 @@ namespace Example.Extension { private string exampleValueFromCommandLine; - public IReadOnlyCollection CommandLineSwitches => throw new NotImplementedException(); + public CommandLineHelp GetCommandLineHelp() + { + return new CommandLineHelp("Example command line extension", "example value", new[] + { + new CommandLineHelpSwitch("-example", "Sets an example value") + }); + } public ExamplePreprocessorExtensionAndCommandLine() { diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/CommandLineFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/CommandLineFixture.cs index 1b0f9633..c1c98252 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/CommandLineFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/CommandLineFixture.cs @@ -22,10 +22,9 @@ namespace WixToolsetTest.CoreIntegration WixAssert.CompareLineByLine(new[] { "-bindpath is expected to be followed by a value. See -? for additional detail.", - "Additional argument '-bindpath' was unexpected. Remove the argument and add the '-?' switch for more information.", - "No source files specified." + "Additional argument '-bindpath' was unexpected. Remove the argument and add the '-?' switch for more information." }, result.Messages.Select(m => m.ToString()).ToArray()); - Assert.Equal(391, result.ExitCode); + Assert.Equal(1, result.ExitCode); } [Fact] -- cgit v1.2.3-55-g6feb