@joebigelow / wix-1 / commits / a6f8b6fa

Redesign command-line help to meet the needs of WiX v4

Rob Mensching committed Aug 11, 2022 at 17:40 UTC a6f8b6fa3903d846cdc2fbe715ca951d83af3107
38 files changed +685 -363
src/api/wix/WixToolset.Extensibility/BaseCommandLineCommand.cs new
+40
@@ -0,0 +1,40 @@
1 +// 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.
2 +
3 +namespace WixToolset.Extensibility
4 +{
5 + using System.Threading;
6 + using System.Threading.Tasks;
7 + using WixToolset.Extensibility.Data;
8 + using WixToolset.Extensibility.Services;
9 +
10 + /// <summary>
11 + /// Base class for a command-line command.
12 + /// </summary>
13 + public abstract class BaseCommandLineCommand : ICommandLineCommand
14 + {
15 + /// <summary>
16 + /// See <see cref="ICommandLineCommand.ShowLogo" />
17 + /// </summary>
18 + public virtual bool ShowLogo => false;
19 +
20 + /// <summary>
21 + /// See <see cref="ICommandLineCommand.StopParsing" />
22 + /// </summary>
23 + public bool StopParsing { get; protected set; }
24 +
25 + /// <summary>
26 + /// See <see cref="ICommandLineCommand.ExecuteAsync" />
27 + /// </summary>
28 + public abstract Task<int> ExecuteAsync(CancellationToken cancellationToken);
29 +
30 + /// <summary>
31 + /// See <see cref="ICommandLineCommand.GetCommandLineHelp" />
32 + /// </summary>
33 + public abstract CommandLineHelp GetCommandLineHelp();
34 +
35 + /// <summary>
36 + /// See <see cref="ICommandLineCommand.TryParseArgument" />
37 + /// </summary>
38 + public abstract bool TryParseArgument(ICommandLineParser parser, string argument);
39 + }
40 +}
src/api/wix/WixToolset.Extensibility/BaseExtensionCommandLine.cs
+5 -4
@@ -2,8 +2,6 @@
2
3 namespace WixToolset.Extensibility
4 {
5 - using System;
6 - using System.Collections.Generic;
5 using WixToolset.Extensibility.Data;
6 using WixToolset.Extensibility.Services;
7
@@ -13,9 +11,12 @@ namespace WixToolset.Extensibility
11 public abstract class BaseExtensionCommandLine : IExtensionCommandLine
12 {
13 /// <summary>
16 - /// See <see cref="IExtensionCommandLine.CommandLineSwitches" />
14 + /// See <see cref="IExtensionCommandLine.GetCommandLineHelp" />
15 /// </summary>
18 - public virtual IReadOnlyCollection<ExtensionCommandLineSwitch> CommandLineSwitches => Array.Empty<ExtensionCommandLineSwitch>();
16 + public virtual CommandLineHelp GetCommandLineHelp()
17 + {
18 + return null;
19 + }
20
21 /// <summary>
22 /// See <see cref="IExtensionCommandLine.PostParse" />
src/api/wix/WixToolset.Extensibility/Data/CommandLineHelp.cs new
+52
@@ -0,0 +1,52 @@
1 +// 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.
2 +
3 +namespace WixToolset.Extensibility.Data
4 +{
5 + using System.Collections.Generic;
6 +
7 + /// <summary>
8 + /// A command line option (switch or command) description.
9 + /// </summary>
10 + public class CommandLineHelp
11 + {
12 + /// <summary>
13 + /// Creates command line help.
14 + /// </summary>
15 + /// <param name="description">Description for the command line option.</param>
16 + /// <param name="usage">Optional usage for the command line option.</param>
17 + /// <param name="switches">Optional list of switches.</param>
18 + /// <param name="commands">Optional list of commands.</param>
19 + public CommandLineHelp(string description, string usage = null, IReadOnlyCollection<CommandLineHelpSwitch> switches = null, IReadOnlyCollection<CommandLineHelpCommand> commands = null)
20 + {
21 + this.Description = description;
22 + this.Usage = usage;
23 + this.Switches = switches;
24 + this.Commands = commands;
25 + }
26 +
27 + /// <summary>
28 + /// Description for the command line option.
29 + /// </summary>
30 + public string Description { get; set; }
31 +
32 + /// <summary>
33 + /// Usage for the command line option.
34 + /// </summary>
35 + public string Usage { get; set; }
36 +
37 + /// <summary>
38 + /// Optional additional notes for the command line option.
39 + /// </summary>
40 + public string Notes { get; set; }
41 +
42 + /// <summary>
43 + /// Optional list of command line switches.
44 + /// </summary>
45 + public IReadOnlyCollection<CommandLineHelpSwitch> Switches { get; set; }
46 +
47 + /// <summary>
48 + /// Optional list of command line commands.
49 + /// </summary>
50 + public IReadOnlyCollection<CommandLineHelpCommand> Commands { get; set; }
51 + }
52 +}
src/api/wix/WixToolset.Extensibility/Data/CommandLineHelpCommand.cs new
+31
@@ -0,0 +1,31 @@
1 +// 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.
2 +
3 +namespace WixToolset.Extensibility.Data
4 +{
5 + /// <summary>
6 + /// A command line command description.
7 + /// </summary>
8 + public class CommandLineHelpCommand
9 + {
10 + /// <summary>
11 + /// Creates help for command line command.
12 + /// </summary>
13 + /// <param name="name">Name of command.</param>
14 + /// <param name="description">Description for command.</param>
15 + public CommandLineHelpCommand(string name, string description)
16 + {
17 + Name = name;
18 + Description = description;
19 + }
20 +
21 + /// <summary>
22 + /// Name of command.
23 + /// </summary>
24 + public string Name { get; set; }
25 +
26 + /// <summary>
27 + /// Description of the command.
28 + /// </summary>
29 + public string Description { get; set; }
30 + }
31 +}
src/api/wix/WixToolset.Extensibility/Data/CommandLineHelpSwitch.cs new
+47
@@ -0,0 +1,47 @@
1 +// 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.
2 +
3 +namespace WixToolset.Extensibility.Data
4 +{
5 + /// <summary>
6 + /// A command line switch description.
7 + /// </summary>
8 + public class CommandLineHelpSwitch
9 + {
10 + /// <summary>
11 + /// Creates help for command line switch.
12 + /// </summary>
13 + /// <param name="name">Name of switch.</param>
14 + /// <param name="description">Description for switch.</param>
15 + public CommandLineHelpSwitch(string name, string description) : this(name, null, description)
16 + {
17 + }
18 +
19 + /// <summary>
20 + /// Creates help for command line switch.
21 + /// </summary>
22 + /// <param name="name">Name of switch.</param>
23 + /// <param name="shortName">Optional short name of switch.</param>
24 + /// <param name="description">Description for switch.</param>
25 + public CommandLineHelpSwitch(string name, string shortName, string description)
26 + {
27 + Name = name;
28 + ShortName = shortName;
29 + Description = description;
30 + }
31 +
32 + /// <summary>
33 + /// Name for switch.
34 + /// </summary>
35 + public string Name { get; set; }
36 +
37 + /// <summary>
38 + /// Optional short name for switch.
39 + /// </summary>
40 + public string ShortName { get; set; }
41 +
42 + /// <summary>
43 + /// Description of the switch.
44 + /// </summary>
45 + public string Description { get; set; }
46 + }
47 +}
src/api/wix/WixToolset.Extensibility/Data/ExtensionCommandLineSwitch.cs deleted
-20
@@ -1,20 +0,0 @@
1 -// 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.
2 -
3 -namespace WixToolset.Extensibility.Data
4 -{
5 - /// <summary>
6 - /// A command line option.
7 - /// </summary>
8 - public struct ExtensionCommandLineSwitch
9 - {
10 - /// <summary>
11 - ///
12 - /// </summary>
13 - public string Switch { get; set; }
14 -
15 - /// <summary>
16 - ///
17 - /// </summary>
18 - public string Description { get; set; }
19 - }
20 -}
src/api/wix/WixToolset.Extensibility/Data/ICommandLineCommand.cs
+6 -6
@@ -12,19 +12,19 @@ namespace WixToolset.Extensibility.Data
12 public interface ICommandLineCommand
13 {
14 /// <summary>
15 - /// Indicates the command-line should show help for the command.
15 + /// Indicates the command-line should show the logo.
16 /// </summary>
17 - bool ShowHelp { get; set; }
17 + bool ShowLogo { get; }
18
19 /// <summary>
20 - /// Indicates the command-line should show the command-line logo.
20 + /// Indicates the command-line parsing can stop.
21 /// </summary>
22 - bool ShowLogo { get; set; }
22 + bool StopParsing { get; }
23
24 /// <summary>
25 - /// Indicates the command-line parsing can stop.
25 + /// Gets the help for this command.
26 /// </summary>
27 - bool StopParsing { get; }
27 + CommandLineHelp GetCommandLineHelp();
28
29 /// <summary>
30 /// Executes the command.
src/api/wix/WixToolset.Extensibility/IExtensionCommandLine.cs
+2 -4
@@ -2,7 +2,6 @@
2
3 namespace WixToolset.Extensibility
4 {
5 - using System.Collections.Generic;
5 using WixToolset.Extensibility.Data;
6 using WixToolset.Extensibility.Services;
7
@@ -12,10 +11,9 @@ namespace WixToolset.Extensibility
11 public interface IExtensionCommandLine
12 {
13 /// <summary>
15 - /// Gets the supported command line types for this extension.
14 + /// Gets the help for this extension.
15 /// </summary>
17 - /// <value>The supported command line types for this extension.</value>
18 - IReadOnlyCollection<ExtensionCommandLineSwitch> CommandLineSwitches { get; }
16 + CommandLineHelp GetCommandLineHelp();
17
18 /// <summary>
19 /// Called before the command-line is parsed.
src/tools/heat/HeatCommand.cs
+13 -9
@@ -11,13 +11,16 @@ namespace WixToolset.Harvesters
11 using System.Threading.Tasks;
12 using System.Xml;
13 using WixToolset.Data;
14 + using WixToolset.Extensibility;
15 using WixToolset.Extensibility.Data;
16 using WixToolset.Extensibility.Services;
17 using WixToolset.Harvesters.Extensibility;
18 using Wix = WixToolset.Harvesters.Serialize;
19
19 - internal class HeatCommand : ICommandLineCommand
20 + internal class HeatCommand : BaseCommandLineCommand
21 {
22 + private bool showLogo;
23 +
24 public HeatCommand(string harvestType, IList<IHeatExtension> extensions, IServiceProvider serviceProvider)
25 {
26 this.Extensions = extensions;
@@ -28,11 +31,7 @@ namespace WixToolset.Harvesters
31 this.ExtensionOptions.Add(harvestType);
32 }
33
31 - public bool ShowHelp { get; set; }
32 -
33 - public bool ShowLogo { get; set; }
34 -
35 - public bool StopParsing { get; private set; }
34 + public override bool ShowLogo => this.showLogo;
35
36 private string ExtensionArgument { get; set; }
37
@@ -50,13 +49,18 @@ namespace WixToolset.Harvesters
49
50 private IServiceProvider ServiceProvider { get; }
51
53 - public Task<int> ExecuteAsync(CancellationToken cancellationToken)
52 + public override CommandLineHelp GetCommandLineHelp()
53 + {
54 + return null;
55 + }
56 +
57 + public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
58 {
59 var exitCode = this.Harvest();
60 return Task.FromResult(exitCode);
61 }
62
59 - public bool TryParseArgument(ICommandLineParser parser, string arg)
63 + public override bool TryParseArgument(ICommandLineParser parser, string arg)
64 {
65 if (this.ExtensionArgument == null)
66 {
@@ -67,7 +71,7 @@ namespace WixToolset.Harvesters
71 string parameter = arg.Substring(1);
72 if ("nologo" == parameter)
73 {
70 - this.ShowLogo = false;
74 + this.showLogo = false;
75 }
76 else if ("o" == parameter || "out" == parameter)
77 {
src/tools/heat/HeatCommandLine.cs
+2 -4
@@ -13,19 +13,17 @@ namespace WixToolset.Harvesters
13
14 internal class HeatCommandLine : IHeatCommandLine
15 {
16 - private readonly List<IHeatExtension> extensions;
17 - private readonly IMessaging messaging;
16 private readonly IServiceProvider serviceProvider;
17 + private readonly List<IHeatExtension> extensions;
18
19 public HeatCommandLine(IServiceProvider serviceProvider, IEnumerable<IHeatExtension> heatExtensions)
20 {
21 + this.serviceProvider = serviceProvider;
22 this.extensions = new List<IHeatExtension> { new IIsHeatExtension(), new UtilHeatExtension(serviceProvider), new VSHeatExtension() };
23 if (heatExtensions != null)
24 {
25 this.extensions.AddRange(heatExtensions);
26 }
27 - this.messaging = serviceProvider.GetService<IMessaging>();
28 - this.serviceProvider = serviceProvider;
27 }
28
29 public ICommandLineCommand ParseStandardCommandLine(ICommandLineArguments arguments)
src/tools/heat/HelpCommand.cs
+7 -10
@@ -8,12 +8,13 @@ namespace WixToolset.Harvesters
8 using System.Diagnostics;
9 using System.Threading;
10 using System.Threading.Tasks;
11 + using WixToolset.Extensibility;
12 using WixToolset.Extensibility.Data;
13 using WixToolset.Extensibility.Services;
14 using WixToolset.Harvesters.Data;
15 using WixToolset.Harvesters.Extensibility;
16
16 - internal class HelpCommand : ICommandLineCommand
17 + internal class HelpCommand : BaseCommandLineCommand
18 {
19 const string HelpMessageOptionFormat = " {0,-7} {1}";
20
@@ -24,17 +25,12 @@ namespace WixToolset.Harvesters
25
26 private IList<IHeatExtension> Extensions { get; }
27
27 - public bool ShowHelp { get; set; }
28 -
29 - public bool ShowLogo
28 + public override CommandLineHelp GetCommandLineHelp()
29 {
31 - get => false;
32 - set { }
30 + return null;
31 }
32
35 - public bool StopParsing => true;
36 -
37 - public Task<int> ExecuteAsync(CancellationToken cancellationToken)
33 + public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
34 {
35 var exitCode = this.DisplayHelp();
36 return Task.FromResult(exitCode);
@@ -50,8 +46,9 @@ namespace WixToolset.Harvesters
46 Console.WriteLine();
47 }
48
53 - public bool TryParseArgument(ICommandLineParser parser, string argument)
49 + public override bool TryParseArgument(ICommandLineParser parser, string argument)
50 {
51 + this.StopParsing = true;
52 return true;
53 }
54
src/wix/WixToolset.Converters/ConvertCommand.cs
+17 -27
@@ -5,27 +5,34 @@ namespace WixToolset.Converters
5 using System;
6 using System.Threading;
7 using System.Threading.Tasks;
8 - using WixToolset.Extensibility.Services;
8 + using WixToolset.Extensibility.Data;
9
10 internal class ConvertCommand : FixupCommandBase
11 {
12 private const string SettingsFileDefault = "wix.convert.settings.xml";
13
14 - public ConvertCommand(IServiceProvider serviceProvider)
14 + public ConvertCommand(IServiceProvider serviceProvider) : base(serviceProvider)
15 {
16 - this.Messaging = serviceProvider.GetService<IMessaging>();
16 }
17
19 - private IMessaging Messaging { get; }
20 -
21 - public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
18 + public override CommandLineHelp GetCommandLineHelp()
19 {
23 - if (this.ShowHelp)
20 + return new CommandLineHelp("Convert v3 source code to v4 source code.", "convert [options] sourceFile [sourceFile ...]")
21 {
25 - DisplayHelp();
26 - return Task.FromResult(-1);
27 - }
22 + Switches = new[]
23 + {
24 + new CommandLineHelpSwitch("--dry-run", "-n", "Only display errors, do not update files."),
25 + new CommandLineHelpSwitch("--recurse", "-r", "Search for matching files in current dir and subdirs."),
26 + new CommandLineHelpSwitch("-set1<file>", "Primary settings file."),
27 + new CommandLineHelpSwitch("-set2<file>", "Secondary settings file (overrides primary)."),
28 + new CommandLineHelpSwitch("-indent:<n>", "Indentation multiple (overrides default of 4)."),
29 + },
30 + Notes = " sourceFile may use wildcards like *.wxs"
31 + };
32 + }
33
34 + public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
35 + {
36 this.ParseSettings(SettingsFileDefault);
37
38 var converter = new WixConverter(this.Messaging, this.IndentationAmount, this.ErrorsAsWarnings, this.IgnoreErrors);
@@ -39,22 +46,5 @@ namespace WixToolset.Converters
46 return converter.ConvertFile(file, fix);
47 }
48 }
42 -
43 - private static void DisplayHelp()
44 - {
45 - Console.WriteLine();
46 - Console.WriteLine("Usage: wix convert [options] sourceFile [sourceFile ...]");
47 - Console.WriteLine();
48 - Console.WriteLine("Options:");
49 - Console.WriteLine(" -h|--help Show command line help.");
50 - Console.WriteLine(" --nologo Suppress displaying the logo information.");
51 - Console.WriteLine(" -n|--dry-run Only display errors, do not update files.");
52 - Console.WriteLine(" -r|--recurse Search for matching files in current dir and subdirs.");
53 - Console.WriteLine(" -set1<file> Primary settings file.");
54 - Console.WriteLine(" -set2<file> Secondary settings file (overrides primary).");
55 - Console.WriteLine(" -indent:<n> Indentation multiple (overrides default of 4).");
56 - Console.WriteLine();
57 - Console.WriteLine(" sourceFile may use wildcards like *.wxs");
58 - }
49 }
50 }
src/wix/WixToolset.Converters/ConverterExtensionCommandLine.cs
+10 -5
@@ -3,7 +3,6 @@
3 namespace WixToolset.Converters
4 {
5 using System;
6 - using System.Collections.Generic;
6 using WixToolset.Extensibility;
7 using WixToolset.Extensibility.Data;
8 using WixToolset.Extensibility.Services;
@@ -21,11 +20,17 @@ namespace WixToolset.Converters
20
21 private IServiceProvider ServiceProvider { get; }
22
24 - public override IReadOnlyCollection<ExtensionCommandLineSwitch> CommandLineSwitches => new ExtensionCommandLineSwitch[]
23 + public override CommandLineHelp GetCommandLineHelp()
24 {
26 - new ExtensionCommandLineSwitch { Switch = "convert", Description = "Convert v3 source code to v4 source code." },
27 - new ExtensionCommandLineSwitch { Switch = "format", Description = "Ensures consistent formatting of source code." },
28 - };
25 + return new CommandLineHelp("Source code converter and formatter.")
26 + {
27 + Commands = new[]
28 + {
29 + new CommandLineHelpCommand("convert", "Convert v3 source code to v4 source code."),
30 + new CommandLineHelpCommand("format", "Ensures consistent formatting of source code."),
31 + }
32 + };
33 + }
34
35 public override bool TryParseCommand(ICommandLineParser parser, string argument, out ICommandLineCommand command)
36 {
src/wix/WixToolset.Converters/FixupCommandBase.cs
+11 -28
@@ -6,15 +6,17 @@ namespace WixToolset.Converters
6 using System.Collections.Generic;
7 using System.IO;
8 using System.Threading;
9 - using System.Threading.Tasks;
9 using System.Xml;
11 - using WixToolset.Extensibility.Data;
10 + using WixToolset.Data;
11 + using WixToolset.Extensibility;
12 using WixToolset.Extensibility.Services;
13
14 - internal abstract class FixupCommandBase : ICommandLineCommand
14 + internal abstract class FixupCommandBase : BaseCommandLineCommand
15 {
16 - protected FixupCommandBase()
16 + protected FixupCommandBase(IServiceProvider serviceProvider)
17 {
18 + this.Messaging = serviceProvider.GetService<IMessaging>();
19 +
20 this.IndentationAmount = 4; // default indentation amount
21 this.ErrorsAsWarnings = new HashSet<string>();
22 this.ExemptFiles = new HashSet<string>();
@@ -23,11 +25,7 @@ namespace WixToolset.Converters
25 this.SearchPatterns = new List<string>();
26 }
27
26 - public bool ShowHelp { get; set; }
27 -
28 - public bool ShowLogo { get; set; }
29 -
30 - public bool StopParsing { get; set; }
28 + protected IMessaging Messaging { get; }
29
30 protected CustomTableTarget CustomTableSetting { get; set; }
31
@@ -43,15 +41,15 @@ namespace WixToolset.Converters
41
42 protected bool Recurse { get; set; }
43
46 - private HashSet<string> SearchPatternResults { get; }
44 + private HashSet<string> SearchPatternResults { get; }
45
48 - private List<string> SearchPatterns { get; }
46 + private List<string> SearchPatterns { get; }
47
48 private string SettingsFile1 { get; set; }
49
50 private string SettingsFile2 { get; set; }
51
54 - public bool TryParseArgument(ICommandLineParser parser, string argument)
52 + public override bool TryParseArgument(ICommandLineParser parser, string argument)
53 {
54 if (!parser.IsSwitch(argument))
55 {
@@ -62,14 +60,6 @@ namespace WixToolset.Converters
60 var parameter = argument.Substring(1);
61 switch (parameter.ToLowerInvariant())
62 {
65 - case "?":
66 - case "h":
67 - case "-help":
68 - this.ShowHelp = true;
69 - this.ShowLogo = true;
70 - this.StopParsing = true;
71 - return true;
72 -
63 case "-custom-table":
64 var customTableSetting = parser.GetNextArgumentOrError(argument);
65 switch (customTableSetting)
@@ -91,11 +81,6 @@ namespace WixToolset.Converters
81 this.DryRun = true;
82 return true;
83
94 - case "nologo":
95 - case "-nologo":
96 - this.ShowLogo = false;
97 - return true;
98 -
84 case "s":
85 case "r":
86 case "-recurse":
@@ -131,8 +116,6 @@ namespace WixToolset.Converters
116 }
117 }
118
134 - public abstract Task<int> ExecuteAsync(CancellationToken cancellationToken);
135 -
119 protected void ParseSettings(string defaultSettingsFile)
120 {
121 // parse the settings if any were specified
@@ -157,7 +140,7 @@ namespace WixToolset.Converters
140 {
141 if (!this.SearchPatternResults.Contains(searchPattern))
142 {
160 - Console.Error.WriteLine("Could not find file \"{0}\"", searchPattern);
143 + this.Messaging.Write(ErrorMessages.FileNotFound(null, searchPattern));
144 errors++;
145 }
146 }
src/wix/WixToolset.Converters/FormatCommand.cs
+18 -28
@@ -5,31 +5,38 @@ namespace WixToolset.Converters
5 using System;
6 using System.Threading;
7 using System.Threading.Tasks;
8 - using WixToolset.Extensibility.Services;
8 + using WixToolset.Extensibility.Data;
9
10 internal class FormatCommand : FixupCommandBase
11 {
12 private const string SettingsFileDefault = "wix.format.settings.xml";
13
14 - public FormatCommand(IServiceProvider serviceProvider)
14 + public FormatCommand(IServiceProvider serviceProvider) : base(serviceProvider)
15 {
16 - this.Messaging = serviceProvider.GetService<IMessaging>();
16 }
17
19 - private IMessaging Messaging { get; }
18 + public override CommandLineHelp GetCommandLineHelp()
19 + {
20 + return new CommandLineHelp("Ensures consistent formatting of source code.", "format [options] sourceFile [sourceFile ...]")
21 + {
22 + Switches = new[]
23 + {
24 + new CommandLineHelpSwitch("--dry-run", "-n", "Only display errors, do not update files."),
25 + new CommandLineHelpSwitch("--recurse", "-r", "Search for matching files in current dir and subdirs."),
26 + new CommandLineHelpSwitch("-set1<file>", "Primary settings file."),
27 + new CommandLineHelpSwitch("-set2<file>", "Secondary settings file (overrides primary)."),
28 + new CommandLineHelpSwitch("-indent:<n>", "Indentation multiple (overrides default of 4)."),
29 + },
30 + Notes = " sourceFile may use wildcards like *.wxs"
31 + };
32 + }
33
34 public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
35 {
23 - if (this.ShowHelp)
24 - {
25 - DisplayHelp();
26 - return Task.FromResult(-1);
27 - }
36 + this.ParseSettings(SettingsFileDefault);
37
38 var converter = new WixConverter(this.Messaging, this.IndentationAmount, this.ErrorsAsWarnings, this.IgnoreErrors);
39
31 - this.ParseSettings(SettingsFileDefault);
32 -
40 var errors = base.Inspect(Inspector, cancellationToken);
41
42 return Task.FromResult(errors);
@@ -39,22 +46,5 @@ namespace WixToolset.Converters
46 return converter.FormatFile(file, fix);
47 }
48 }
42 -
43 - private static void DisplayHelp()
44 - {
45 - Console.WriteLine();
46 - Console.WriteLine("Usage: wix format [options] sourceFile [sourceFile ...]");
47 - Console.WriteLine();
48 - Console.WriteLine("Options:");
49 - Console.WriteLine(" -h|--help Show command line help.");
50 - Console.WriteLine(" --nologo Suppress displaying the logo information.");
51 - Console.WriteLine(" -n|--dry-run Only display errors, do not update files.");
52 - Console.WriteLine(" -r|--recurse Search for matching files in current dir and subdirs.");
53 - Console.WriteLine(" -set1<file> Primary settings file.");
54 - Console.WriteLine(" -set2<file> Secondary settings file (overrides primary).");
55 - Console.WriteLine(" -indent:<n> Indentation multiple (overrides default of 4).");
56 - Console.WriteLine();
57 - Console.WriteLine(" sourceFile may use wildcards like *.wxs");
58 - }
49 }
50 }
src/wix/WixToolset.Core.Burn/BurnExtensionCommandLine.cs
+6 -4
@@ -3,7 +3,6 @@
3 namespace WixToolset.Core.Burn
4 {
5 using System;
6 - using System.Collections.Generic;
6 using WixToolset.Core.Burn.CommandLine;
7 using WixToolset.Extensibility;
8 using WixToolset.Extensibility.Data;
@@ -22,10 +21,13 @@ namespace WixToolset.Core.Burn
21
22 private IServiceProvider ServiceProvider { get; }
23
25 - public override IReadOnlyCollection<ExtensionCommandLineSwitch> CommandLineSwitches => new ExtensionCommandLineSwitch[]
24 + public override CommandLineHelp GetCommandLineHelp()
25 {
27 - new ExtensionCommandLineSwitch { Switch = "burn", Description = "Burn specialized operations." },
28 - };
26 + return new CommandLineHelp(null)
27 + {
28 + Commands = new[] { new CommandLineHelpCommand("burn", "Specialized operations for manipulating Burn-based bundles.") }
29 + };
30 + }
31
32 public override bool TryParseCommand(ICommandLineParser parser, string argument, out ICommandLineCommand command)
33 {
src/wix/WixToolset.Core.Burn/CommandLine/BurnCommand.cs
+20 -26
@@ -5,41 +5,50 @@ namespace WixToolset.Core.Burn.CommandLine
5 using System;
6 using System.Threading;
7 using System.Threading.Tasks;
8 + using WixToolset.Extensibility;
9 using WixToolset.Extensibility.Data;
10 using WixToolset.Extensibility.Services;
11
12 /// <summary>
13 /// Burn specialized command.
14 /// </summary>
14 - internal class BurnCommand : ICommandLineCommand
15 + internal class BurnCommand : BaseCommandLineCommand
16 {
17 public BurnCommand(IServiceProvider serviceProvider)
18 {
19 this.ServiceProvider = serviceProvider;
20 }
21
21 - public bool ShowHelp { get; set; }
22 -
23 - public bool ShowLogo { get; set; }
24 -
25 - public bool StopParsing { get; set; }
26 -
22 private IServiceProvider ServiceProvider { get; }
23
24 private BurnSubcommandBase Subcommand { get; set; }
25
31 - public Task<int> ExecuteAsync(CancellationToken cancellationToken)
26 + public override CommandLineHelp GetCommandLineHelp()
27 {
33 - if (this.ShowHelp || this.Subcommand is null)
28 + return this.Subcommand?.GetCommandLineHelp() ?? new CommandLineHelp("Specialized operations for manipulating Burn-based bundles.", "burn detach|extract|reattach|remotepayload")
29 {
35 - DisplayHelp();
30 + Commands = new[]
31 + {
32 + new CommandLineHelpCommand("detach", "Detaches the burn engine from a bundle so it can be signed."),
33 + new CommandLineHelpCommand("extract", "Extracts the internals of a bundle to a folder."),
34 + new CommandLineHelpCommand("reattach", "Reattaches a signed burn engine to a bundle."),
35 + new CommandLineHelpCommand("remotepayload", "Extracts the internals of a bundle."),
36 + }
37 + };
38 + }
39 +
40 + public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
41 + {
42 + if (this.Subcommand is null)
43 + {
44 + Console.Error.WriteLine("A subcommand is required for the \"burn\" command. Add -h to for help.");
45 return Task.FromResult(1);
46 }
47
48 return this.Subcommand.ExecuteAsync(cancellationToken);
49 }
50
42 - public bool TryParseArgument(ICommandLineParser parser, string argument)
51 + public override bool TryParseArgument(ICommandLineParser parser, string argument)
52 {
53 if (this.Subcommand is null)
54 {
@@ -67,20 +76,5 @@ namespace WixToolset.Core.Burn.CommandLine
76
77 return this.Subcommand.TryParseArgument(parser, argument);
78 }
70 -
71 - private static void DisplayHelp()
72 - {
73 - Console.WriteLine();
74 - Console.WriteLine("Usage: wix burn detach|reattach bundle.exe -out engine.exe");
75 - Console.WriteLine();
76 - Console.WriteLine("Options:");
77 - Console.WriteLine(" -h|--help Show command line help.");
78 - Console.WriteLine(" --nologo Suppress displaying the logo information.");
79 - Console.WriteLine();
80 - Console.WriteLine("Commands:");
81 - Console.WriteLine();
82 - Console.WriteLine(" detach Detaches the burn engine from a bundle so it can be signed.");
83 - Console.WriteLine(" reattach Reattaches a signed burn engine to a bundle.");
84 - }
79 }
80 }
src/wix/WixToolset.Core.Burn/CommandLine/BurnSubcommandBase.cs
+3
@@ -4,10 +4,13 @@ namespace WixToolset.Core.Burn.CommandLine
4 {
5 using System.Threading;
6 using System.Threading.Tasks;
7 + using WixToolset.Extensibility.Data;
8 using WixToolset.Extensibility.Services;
9
10 internal abstract class BurnSubcommandBase
11 {
12 + public abstract CommandLineHelp GetCommandLineHelp();
13 +
14 public abstract bool TryParseArgument(ICommandLineParser parser, string argument);
15
16 public abstract Task<int> ExecuteAsync(CancellationToken cancellationToken);
src/wix/WixToolset.Core.Burn/CommandLine/DetachSubcommand.cs
+10
@@ -7,6 +7,7 @@ namespace WixToolset.Core.Burn.CommandLine
7 using System.Threading;
8 using System.Threading.Tasks;
9 using WixToolset.Core.Burn.Inscribe;
10 + using WixToolset.Extensibility.Data;
11 using WixToolset.Extensibility.Services;
12
13 internal class DetachSubcommand : BurnSubcommandBase
@@ -27,6 +28,15 @@ namespace WixToolset.Core.Burn.CommandLine
28
29 private string EngineOutputPath { get; set; }
30
31 + public override CommandLineHelp GetCommandLineHelp()
32 + {
33 + return new CommandLineHelp("Detaches the burn engine from a bundle so it can be signed.", "burn detach [options] original.exe -engine engine.exe", new[]
34 + {
35 + new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."),
36 + new CommandLineHelpSwitch("-engine", "Path to extract bundle's engine file to."),
37 + });
38 + }
39 +
40 public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
41 {
42 if (String.IsNullOrEmpty(this.InputPath))
src/wix/WixToolset.Core.Burn/CommandLine/ExtractSubcommand.cs
+11
@@ -7,6 +7,7 @@ namespace WixToolset.Core.Burn.CommandLine
7 using System.Threading;
8 using System.Threading.Tasks;
9 using WixToolset.Core.Burn.Bundles;
10 + using WixToolset.Extensibility.Data;
11 using WixToolset.Extensibility.Services;
12
13 internal class ExtractSubcommand : BurnSubcommandBase
@@ -27,6 +28,15 @@ namespace WixToolset.Core.Burn.CommandLine
28
29 private string ExtractPath { get; set; }
30
31 + public override CommandLineHelp GetCommandLineHelp()
32 + {
33 + return new CommandLineHelp("Extracts the internals of a bundle to a folder.", "burn extract [options] bundle.exe -o outputfolder ", new[]
34 + {
35 + new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."),
36 + new CommandLineHelpSwitch("-out", "-o", "Folder to extract the bundle contents to."),
37 + });
38 + }
39 +
40 public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
41 {
42 if (String.IsNullOrEmpty(this.InputPath))
@@ -77,6 +87,7 @@ namespace WixToolset.Core.Burn.CommandLine
87 return true;
88
89 case "o":
90 + case "out":
91 this.ExtractPath = parser.GetNextArgumentAsDirectoryOrError(argument);
92 return true;
93 }
src/wix/WixToolset.Core.Burn/CommandLine/ReattachSubcommand.cs
+10
@@ -7,6 +7,7 @@ namespace WixToolset.Core.Burn.CommandLine
7 using System.Threading;
8 using System.Threading.Tasks;
9 using WixToolset.Core.Burn.Inscribe;
10 + using WixToolset.Extensibility.Data;
11 using WixToolset.Extensibility.Services;
12
13 internal class ReattachSubcommand : BurnSubcommandBase
@@ -29,6 +30,15 @@ namespace WixToolset.Core.Burn.CommandLine
30
31 private string OutputPath { get; set; }
32
33 + public override CommandLineHelp GetCommandLineHelp()
34 + {
35 + return new CommandLineHelp("Reattaches a signed burn engine to a bundle.", "burn reattach [options] original.exe signed.exe -o final.exe", new[]
36 + {
37 + new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."),
38 + new CommandLineHelpSwitch("-out", "-o", "Output bundle with signed engine attached."),
39 + });
40 + }
41 +
42 public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
43 {
44 if (String.IsNullOrEmpty(this.InputPath))
src/wix/WixToolset.Core.Burn/CommandLine/RemotePayloadSubcommand.cs
+31
@@ -15,6 +15,7 @@ namespace WixToolset.Core.Burn.CommandLine
15 using WixToolset.Data;
16 using WixToolset.Data.Symbols;
17 using WixToolset.Extensibility;
18 + using WixToolset.Extensibility.Data;
19 using WixToolset.Extensibility.Services;
20
21 internal class RemotePayloadSubcommand : BurnSubcommandBase
@@ -66,6 +67,36 @@ namespace WixToolset.Core.Burn.CommandLine
67
68 private bool UseCertificate { get; set; }
69
70 + public override CommandLineHelp GetCommandLineHelp()
71 + {
72 + return new CommandLineHelp("Generate source code for a remote payload", "burn remotepayload [options] payloadfile [payloadfile ...]", new[]
73 + {
74 + new CommandLineHelpSwitch("-basepath", "-bp", "Folder as base to make payloads relative."),
75 + new CommandLineHelpSwitch("-bundlepayloadgeneration", "Sets the package payload generation option; see the Payload Generation Types below."),
76 + new CommandLineHelpSwitch("-downloadurl", "-du", "Set the DownloadUrl attribute on the generated payloads."),
77 + new CommandLineHelpSwitch("-out", "-o", "Path to output the source code file."),
78 + new CommandLineHelpSwitch("-recurse", "-r", "Indicates to add all payloads in directory recursively."),
79 + new CommandLineHelpSwitch("-intermediatefolder", "Optional working folder. If not specified %TMP% folder will be created."),
80 + new CommandLineHelpSwitch("-packagetype", "Explicitly set package type; see the Pacakge Types below."),
81 + new CommandLineHelpSwitch("-usecertificate", "Use certificate to validate signed payloads. This option is not recommended."),
82 + })
83 + {
84 + Notes = String.Join(Environment.NewLine,
85 + "Payload Generation Types:",
86 + " none",
87 + " externalwithoutdownloadurl",
88 + " external",
89 + " all",
90 + String.Empty,
91 + "Package Types:",
92 + " bundle",
93 + " exe",
94 + " msi",
95 + " msp",
96 + " msu")
97 + };
98 + }
99 +
100 public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
101 {
102 var inputPaths = this.ExpandInputPaths();
src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManagerCommand.cs
+25 -44
@@ -7,13 +7,14 @@ namespace WixToolset.Core.ExtensionCache
7 using System.Linq;
8 using System.Threading;
9 using System.Threading.Tasks;
10 + using WixToolset.Extensibility;
11 using WixToolset.Extensibility.Data;
12 using WixToolset.Extensibility.Services;
13
14 /// <summary>
15 /// Extension cache manager command.
16 /// </summary>
16 - internal class ExtensionCacheManagerCommand : ICommandLineCommand
17 + internal class ExtensionCacheManagerCommand : BaseCommandLineCommand
18 {
19 private enum CacheSubcommand
20 {
@@ -29,12 +30,6 @@ namespace WixToolset.Core.ExtensionCache
30 this.ExtensionReferences = new List<string>();
31 }
32
32 - public bool ShowHelp { get; set; }
33 -
34 - public bool ShowLogo { get; set; }
35 -
36 - public bool StopParsing { get; set; }
37 -
33 private IMessaging Messaging { get; }
34
35 private IExtensionManager ExtensionManager { get; }
@@ -45,12 +40,30 @@ namespace WixToolset.Core.ExtensionCache
40
41 private List<string> ExtensionReferences { get; }
42
48 - public async Task<int> ExecuteAsync(CancellationToken cancellationToken)
43 + public override CommandLineHelp GetCommandLineHelp()
44 + {
45 + return new CommandLineHelp("Manage the extension cache.", "extension add|remove|list [options] [extensionRef]")
46 + {
47 + Switches = new[]
48 + {
49 + new CommandLineHelpSwitch("--global", "-g", "Add/remove the extension for the current user."),
50 + },
51 + Commands = new[]
52 + {
53 + new CommandLineHelpCommand("add", "Add extension to the cache."),
54 + new CommandLineHelpCommand("list", "List extensions in the cache."),
55 + new CommandLineHelpCommand("remove", "Remove extension from the cache."),
56 + },
57 + Notes = " extensionRef format: extensionId/version (the version is optional)"
58 + };
59 + }
60 +
61 + public override async Task<int> ExecuteAsync(CancellationToken cancellationToken)
62 {
50 - if (this.ShowHelp || !this.Subcommand.HasValue)
63 + if (!this.Subcommand.HasValue)
64 {
52 - DisplayHelp();
53 - return 1;
65 + Console.Error.WriteLine("A subcommand is required for the \"extension\" command. Use -h to for help.");
66 + return -1;
67 }
68
69 var success = false;
@@ -74,7 +87,7 @@ namespace WixToolset.Core.ExtensionCache
87 return success ? 0 : 2;
88 }
89
77 - public bool TryParseArgument(ICommandLineParser parser, string argument)
90 + public override bool TryParseArgument(ICommandLineParser parser, string argument)
91 {
92 if (!parser.IsSwitch(argument))
93 {
@@ -98,19 +111,6 @@ namespace WixToolset.Core.ExtensionCache
111 var parameter = argument.Substring(1);
112 switch (parameter.ToLowerInvariant())
113 {
101 - case "?":
102 - case "h":
103 - case "-help":
104 - this.ShowHelp = true;
105 - this.ShowLogo = true;
106 - this.StopParsing = true;
107 - return true;
108 -
109 - case "nologo":
110 - case "-nologo":
111 - this.ShowLogo = false;
112 - return true;
113 -
114 case "g":
115 case "-global":
116 this.Global = true;
@@ -161,24 +161,5 @@ namespace WixToolset.Core.ExtensionCache
161
162 return found;
163 }
164 -
165 - private static void DisplayHelp()
166 - {
167 - Console.WriteLine();
168 - Console.WriteLine("Usage: wix extension add|remove|list [extensionRef]");
169 - Console.WriteLine();
170 - Console.WriteLine("Options:");
171 - Console.WriteLine(" -h|--help Show command line help.");
172 - Console.WriteLine(" -g|--global Add/remove the extension for the current user.");
173 - Console.WriteLine(" --nologo Suppress displaying the logo information.");
174 - Console.WriteLine();
175 - Console.WriteLine("Commands:");
176 - Console.WriteLine();
177 - Console.WriteLine(" add Add extension to the cache.");
178 - Console.WriteLine(" list List extensions in the cache.");
179 - Console.WriteLine(" remove Remove extension from the cache.");
180 - Console.WriteLine();
181 - Console.WriteLine(" extensionRef format: extensionId/version (the version is optional)");
182 - }
164 }
165 }
src/wix/WixToolset.Core.ExtensionCache/ExtensionCacheManagerExtensionCommandLine.cs
+6 -4
@@ -3,7 +3,6 @@
3 namespace WixToolset.Core.ExtensionCache
4 {
5 using System;
6 - using System.Collections.Generic;
6 using WixToolset.Extensibility;
7 using WixToolset.Extensibility.Data;
8 using WixToolset.Extensibility.Services;
@@ -21,10 +20,13 @@ namespace WixToolset.Core.ExtensionCache
20
21 private IServiceProvider ServiceProvider { get; }
22
24 - public override IReadOnlyCollection<ExtensionCommandLineSwitch> CommandLineSwitches => new ExtensionCommandLineSwitch[]
23 + public override CommandLineHelp GetCommandLineHelp()
24 {
26 - new ExtensionCommandLineSwitch { Switch = "extension", Description = "Manage extension cache." },
27 - };
25 + return new CommandLineHelp("Manage the extension cache.")
26 + {
27 + Commands = new[] { new CommandLineHelpCommand("extension", "Manage extension cache.") }
28 + };
29 + }
30
31 public override bool TryParseCommand(ICommandLineParser parser, string argument, out ICommandLineCommand command)
32 {
src/wix/WixToolset.Core.WindowsInstaller/CommandLine/DecompilerSubcommand.cs
+16
@@ -42,6 +42,22 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
42
43 private bool SuppressUI { get; set; }
44
45 + public override CommandLineHelp GetCommandLineHelp()
46 + {
47 + return new CommandLineHelp("Converts a Windows Installer database back into source code.", "msi decompile [options] inputfile", new[]
48 + {
49 + new CommandLineHelpSwitch("-cub", "Optional path to a custom validation .CUBe file."),
50 + new CommandLineHelpSwitch("-sct", "Suppress decompiling custom tables."),
51 + new CommandLineHelpSwitch("-sdet", "Suppress dropping empty tables."),
52 + new CommandLineHelpSwitch("-sras", "Suppress relative action sequencing."),
53 + new CommandLineHelpSwitch("-sui", "Suppress decompiling UI tables."),
54 + new CommandLineHelpSwitch("-type", "Optional specify the input file type: msi or msm. If not specified, type will be inferred by file extension."),
55 + new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."),
56 + new CommandLineHelpSwitch("-out", "-o", "Path to output the decompiled .wxs file. If not specified, outputs next to inputfile"),
57 + new CommandLineHelpSwitch("-x", "Folder to export embedded binaries and icons to."),
58 + });
59 + }
60 +
61 public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
62 {
63 if (String.IsNullOrEmpty(this.InputPath))
src/wix/WixToolset.Core.WindowsInstaller/CommandLine/InscribeSubcommand.cs
+10
@@ -7,6 +7,7 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
7 using System.Threading;
8 using System.Threading.Tasks;
9 using WixToolset.Core.WindowsInstaller.Inscribe;
10 + using WixToolset.Extensibility.Data;
11 using WixToolset.Extensibility.Services;
12
13 internal class InscribeSubcommand : WindowsInstallerSubcommandBase
@@ -27,6 +28,15 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
28
29 private string OutputPath { get; set; }
30
31 + public override CommandLineHelp GetCommandLineHelp()
32 + {
33 + return new CommandLineHelp("Updates MSI database with cabinet signature information.", "msi inscribe [options] input.msi [-out inscribed.msi]", new[]
34 + {
35 + new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."),
36 + new CommandLineHelpSwitch("-out", "-o", "Path to output the inscribed MSI. If not provided, the input MSI is updated in place."),
37 + });
38 + }
39 +
40 public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
41 {
42 if (String.IsNullOrEmpty(this.InputPath))
src/wix/WixToolset.Core.WindowsInstaller/CommandLine/TransformSubcommand.cs
+47
@@ -12,6 +12,7 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
12 using WixToolset.Data.Symbols;
13 using WixToolset.Data.WindowsInstaller;
14 using WixToolset.Extensibility;
15 + using WixToolset.Extensibility.Data;
16 using WixToolset.Extensibility.Services;
17
18 internal class TransformSubcommand : WindowsInstallerSubcommandBase
@@ -51,6 +52,52 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
52
53 private TransformFlags ValidationFlags { get; set; }
54
55 + public override CommandLineHelp GetCommandLineHelp()
56 + {
57 + return new CommandLineHelp("Creates an MST transform file.", "msi transform [options] target.msi [updated.msi] -out output.mst")
58 + {
59 + Switches = new[]
60 + {
61 + new CommandLineHelpSwitch("-a", "Admin image, generates source file information in the transform."),
62 + new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."),
63 + new CommandLineHelpSwitch("-p", "Preserve unchanged rows."),
64 + new CommandLineHelpSwitch("-pedantic", "Show pedantic messages."),
65 + new CommandLineHelpSwitch("-serr <flags>", "Suppress error when applying transform; see Error flags below"),
66 + new CommandLineHelpSwitch("-t <type>", "Use default validation flags for the transform type; see Transform types below"),
67 + new CommandLineHelpSwitch("-val <flags>", "Validation flags for the transform; see Validation flags below"),
68 + new CommandLineHelpSwitch("-x", "Folder to extract binaries."),
69 + new CommandLineHelpSwitch("-xo", "Output transfrom as a WiX output instead of an MST file."),
70 + new CommandLineHelpSwitch("-out", "-o", "Path to output the transform file."),
71 + },
72 + Notes = String.Join(Environment.NewLine,
73 + "Error flags:",
74 + " a Ignore errors when adding an existing row",
75 + " b Ignore errors when deleting a missing row",
76 + " c Ignore errors when adding an existing table",
77 + " d Ignore errors when deleting a missing table",
78 + " e Ignore errors when modifying a missing row",
79 + " f Ignore errors when changing the code page",
80 + String.Empty,
81 + "Validation flags:",
82 + " g UpgradeCode must match",
83 + " l Language must match",
84 + " r Product ID must match",
85 + " s Check major version only",
86 + " t Check major and minor versions",
87 + " u Check major, minor, and upgrade versions",
88 + " v Upgrade version < target version",
89 + " w Upgrade version <= target version",
90 + " x Upgrade version = target version",
91 + " y Upgrade version > target version",
92 + " z Upgrade version >= target version",
93 + String.Empty,
94 + "Transform types:",
95 + " language Default flags for a language transform",
96 + " instance Default flags for an instance transform",
97 + " patch Default flags for a patch transform")
98 + };
99 + }
100 +
101 public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
102 {
103 if (String.IsNullOrEmpty(this.TargetPath))
src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs
+13
@@ -9,6 +9,7 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
9 using System.Threading.Tasks;
10 using WixToolset.Core.WindowsInstaller.Validate;
11 using WixToolset.Data.WindowsInstaller;
12 + using WixToolset.Extensibility.Data;
13 using WixToolset.Extensibility.Services;
14
15 internal class ValidateSubcommand : WindowsInstallerSubcommandBase
@@ -35,6 +36,18 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
36
37 private List<string> SuppressIces { get; } = new List<string>();
38
39 + public override CommandLineHelp GetCommandLineHelp()
40 + {
41 + return new CommandLineHelp("Validates MSI database using standard or custom ICEs.", "msi validate [options] inputfile", new[]
42 + {
43 + new CommandLineHelpSwitch("-cub", "Optional path to a custom validation .CUBe file."),
44 + new CommandLineHelpSwitch("-ice", "Validates only with the specified ICE. May be provided multiple times."),
45 + new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."),
46 + new CommandLineHelpSwitch("-pdb", "Optional path to .wixpdb for source line information. If not provided, will check next to the input file."),
47 + new CommandLineHelpSwitch("-sice", "Suppresses an ICE validator."),
48 + });
49 + }
50 +
51 public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
52 {
53 WindowsInstallerData data = null;
src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerCommand.cs
+20 -27
@@ -5,41 +5,50 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
5 using System;
6 using System.Threading;
7 using System.Threading.Tasks;
8 + using WixToolset.Extensibility;
9 using WixToolset.Extensibility.Data;
10 using WixToolset.Extensibility.Services;
11
12 /// <summary>
13 /// Windows Installer specialized command.
14 /// </summary>
14 - internal class WindowsInstallerCommand : ICommandLineCommand
15 + internal class WindowsInstallerCommand : BaseCommandLineCommand
16 {
17 public WindowsInstallerCommand(IServiceProvider serviceProvider)
18 {
19 this.ServiceProvider = serviceProvider;
20 }
21
21 - public bool ShowHelp { get; set; }
22 -
23 - public bool ShowLogo { get; set; }
24 -
25 - public bool StopParsing { get; set; }
26 -
22 private IServiceProvider ServiceProvider { get; }
23
24 private WindowsInstallerSubcommandBase Subcommand { get; set; }
25
31 - public Task<int> ExecuteAsync(CancellationToken cancellationToken)
26 + public override CommandLineHelp GetCommandLineHelp()
27 {
33 - if (this.ShowHelp || this.Subcommand is null)
28 + return this.Subcommand?.GetCommandLineHelp() ?? new CommandLineHelp("Specialized operations for manipulating Windows Installer databases.", "msi decompile|inscribe|transform|validate")
29 {
35 - DisplayHelp();
30 + Commands = new[]
31 + {
32 + new CommandLineHelpCommand("decompile", "Converts a Windows Installer database back into source code."),
33 + new CommandLineHelpCommand("inscribe", "Updates MSI database with cabinet signature information."),
34 + new CommandLineHelpCommand("transform", "Creates an MST transform file."),
35 + new CommandLineHelpCommand("validate", "Validates MSI database using standard or custom ICEs."),
36 + }
37 + };
38 + }
39 +
40 + public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
41 + {
42 + if (this.Subcommand is null)
43 + {
44 + Console.Error.WriteLine("A subcommand is required for the \"msi\" command. Add -h to for help.");
45 return Task.FromResult(1);
46 }
47
48 return this.Subcommand.ExecuteAsync(cancellationToken);
49 }
50
42 - public bool TryParseArgument(ICommandLineParser parser, string argument)
51 + public override bool TryParseArgument(ICommandLineParser parser, string argument)
52 {
53 if (this.Subcommand is null)
54 {
@@ -67,21 +76,5 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
76
77 return this.Subcommand.TryParseArgument(parser, argument);
78 }
70 -
71 - private static void DisplayHelp()
72 - {
73 - Console.WriteLine();
74 - Console.WriteLine("Usage: wix msi inscribe input.msi [-intermedidateFolder folder] [-out output.msi]");
75 - Console.WriteLine();
76 - Console.WriteLine("Options:");
77 - Console.WriteLine(" -h|--help Show command line help.");
78 - Console.WriteLine(" --nologo Suppress displaying the logo information.");
79 - Console.WriteLine();
80 - Console.WriteLine("Commands:");
81 - Console.WriteLine();
82 - Console.WriteLine(" inscribe Updates MSI database with cabinet signature information.");
83 - Console.WriteLine(" transform Creates an MST transform file.");
84 - Console.WriteLine(" validate Validates MSI database using standard or custom ICEs.");
85 - }
79 }
80 }
src/wix/WixToolset.Core.WindowsInstaller/CommandLine/WindowsInstallerSubcommandBase.cs
+3
@@ -4,10 +4,13 @@ namespace WixToolset.Core.WindowsInstaller.CommandLine
4 {
5 using System.Threading;
6 using System.Threading.Tasks;
7 + using WixToolset.Extensibility.Data;
8 using WixToolset.Extensibility.Services;
9
10 internal abstract class WindowsInstallerSubcommandBase
11 {
12 + public abstract CommandLineHelp GetCommandLineHelp();
13 +
14 public abstract bool TryParseArgument(ICommandLineParser parser, string argument);
15
16 public abstract Task<int> ExecuteAsync(CancellationToken cancellationToken);
src/wix/WixToolset.Core.WindowsInstaller/WindowsInstallerExtensionCommandLine.cs
+9 -4
@@ -3,7 +3,6 @@
3 namespace WixToolset.Core.WindowsInstaller
4 {
5 using System;
6 - using System.Collections.Generic;
6 using WixToolset.Core.WindowsInstaller.CommandLine;
7 using WixToolset.Extensibility;
8 using WixToolset.Extensibility.Data;
@@ -22,10 +21,16 @@ namespace WixToolset.Core.WindowsInstaller
21
22 private IServiceProvider ServiceProvider { get; }
23
25 - public override IReadOnlyCollection<ExtensionCommandLineSwitch> CommandLineSwitches => new ExtensionCommandLineSwitch[]
24 + public override CommandLineHelp GetCommandLineHelp()
25 {
27 - new ExtensionCommandLineSwitch { Switch = "msi", Description = "Windows Installer specialized operations." },
28 - };
26 + return new CommandLineHelp("Specialized operations for manipulating Windows Installer databases.")
27 + {
28 + Commands = new[]
29 + {
30 + new CommandLineHelpCommand("msi", "Windows Installer specialized operations."),
31 + }
32 + };
33 + }
34
35 public override bool TryParseCommand(ICommandLineParser parser, string argument, out ICommandLineCommand command)
36 {
src/wix/WixToolset.Core/CommandLine/BuildCommand.cs
+37 -29
@@ -14,7 +14,7 @@ namespace WixToolset.Core.CommandLine
14 using WixToolset.Extensibility.Data;
15 using WixToolset.Extensibility.Services;
16
17 - internal class BuildCommand : ICommandLineCommand
17 + internal class BuildCommand : BaseCommandLineCommand
18 {
19 private readonly CommandLine commandLine;
20
@@ -26,21 +26,6 @@ namespace WixToolset.Core.CommandLine
26 this.commandLine = new CommandLine(this.ServiceProvider, this.Messaging);
27 }
28
29 - public bool ShowHelp
30 - {
31 - get { return this.commandLine.ShowHelp; }
32 - set { this.commandLine.ShowHelp = value; }
33 - }
34 -
35 - public bool ShowLogo
36 - {
37 - get { return this.commandLine.ShowLogo; }
38 - set { this.commandLine.ShowLogo = value; }
39 - }
40 -
41 - // Stop parsing when we've decided to show help.
42 - public bool StopParsing => this.commandLine.ShowHelp;
43 -
29 private IServiceProvider ServiceProvider { get; }
30
31 private IMessaging Messaging { get; }
@@ -57,14 +42,40 @@ namespace WixToolset.Core.CommandLine
42
43 private string TrackingFile { get; set; }
44
60 - public Task<int> ExecuteAsync(CancellationToken cancellationToken)
45 + public override CommandLineHelp GetCommandLineHelp()
46 {
62 - if (this.commandLine.ShowHelp)
47 + return new CommandLineHelp("", "build [options] sourcevile [sourcefile ...] -out output.ext", new[]
48 {
64 - Console.WriteLine("TODO: Show build command help");
65 - return Task.FromResult(-1);
66 - }
49 + new CommandLineHelpSwitch("-arch", "Set the architecture of the output."),
50 + new CommandLineHelpSwitch("-bindfiles", "-bf", "Bind files into an output .wixlib. Ignored if not building a .wixlib."),
51 + new CommandLineHelpSwitch("-bindpath", "Bind path to search for content files."),
52 + new CommandLineHelpSwitch("-cabcache", "-cc", "Set a folder to cache cabinets across builds."),
53 + new CommandLineHelpSwitch("-culture", "Adds a culture to filter localization files."),
54 + new CommandLineHelpSwitch("-define", "-d", "Sets a preprocessor variable."),
55 + new CommandLineHelpSwitch("-defaultcompressionlevel", "-dcl", "Default compression level; see Compression levels below."),
56 + new CommandLineHelpSwitch("-include", "-i", "Folder to search for include files."),
57 + new CommandLineHelpSwitch("-intermediatefolder", "Optional working folder. If not specified a folder in %TMP% will be created."),
58 + new CommandLineHelpSwitch("-loc", "Localization file to use in the build. By default, .wxl files are recognized as localization."),
59 + new CommandLineHelpSwitch("-lib", "Library file to use in the build. By default, .wixlb files are recognized as libraries."),
60 + new CommandLineHelpSwitch("-src", "Source file to use in the build. By default, .wxs files are recognized as source code."),
61 + new CommandLineHelpSwitch("-out", "-o", "Path to output the build to."),
62 + new CommandLineHelpSwitch("-outputtype", "Explicitly set the output type if it cannot be determined from the output."),
63 + new CommandLineHelpSwitch("-pdb", "Optional path to output .wixpdb. Default will write .wixpdb beside output path."),
64 + new CommandLineHelpSwitch("-pdbtype", "Switch to disable creation of .wixpdb. Types: full or none."),
65 + })
66 + {
67 + Notes = String.Join(Environment.NewLine,
68 + "Compression levels:",
69 + " none Use no compression",
70 + " low Use low compression",
71 + " medium Use medium compression",
72 + " high Use high compression",
73 + " mszip Use ms-zip compression")
74 + };
75 + }
76
77 + public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
78 + {
79 this.IntermediateFolder = this.commandLine.CalculateIntermedateFolder();
80
81 this.Platform = this.commandLine.Platform;
@@ -144,7 +155,7 @@ namespace WixToolset.Core.CommandLine
155 return Task.FromResult(this.Messaging.LastErrorNumber);
156 }
157
147 - public bool TryParseArgument(ICommandLineParser parser, string argument)
158 + public override bool TryParseArgument(ICommandLineParser parser, string argument)
159 {
160 return this.commandLine.TryParseArgument(argument, parser);
161 }
@@ -465,7 +476,7 @@ namespace WixToolset.Core.CommandLine
476
477 public List<string> SourceFilePaths { get; } = new List<string>();
478
468 - public List<string> UnevaluatedInputFilePaths { get; } = new List<string>();
479 + public List<string> UnclassifiedInputFilePaths { get; } = new List<string>();
480
481 public Platform Platform { get; private set; }
482
@@ -473,10 +484,6 @@ namespace WixToolset.Core.CommandLine
484
485 public PdbType PdbType { get; private set; }
486
476 - public bool ShowLogo { get; set; }
477 -
478 - public bool ShowHelp { get; set; }
479 -
487 public string IntermediateFolder { get; private set; }
488
489 public string OutputFile { get; private set; }
@@ -535,6 +542,7 @@ namespace WixToolset.Core.CommandLine
542 }
543
544 case "cc":
545 + case "cabcache":
546 this.CabCachePath = parser.GetNextArgumentOrError(arg);
547 return true;
548
@@ -617,7 +625,7 @@ namespace WixToolset.Core.CommandLine
625 }
626 else
627 {
620 - parser.GetArgumentAsFilePathOrError(arg, "input file", this.UnevaluatedInputFilePaths);
628 + parser.GetArgumentAsFilePathOrError(arg, "input file", this.UnclassifiedInputFilePaths);
629 return true;
630 }
631 }
@@ -737,7 +745,7 @@ namespace WixToolset.Core.CommandLine
745 var outputPath = this.OutputFile;
746 var outputType = this.CalculateOutputType();
747
740 - foreach (var path in this.UnevaluatedInputFilePaths)
748 + foreach (var path in this.UnclassifiedInputFilePaths)
749 {
750 var extension = Path.GetExtension(path);
751
src/wix/WixToolset.Core/CommandLine/CommandLine.cs
+32 -18
@@ -21,6 +21,10 @@ namespace WixToolset.Core.CommandLine
21
22 private IMessaging Messaging { get; }
23
24 + private bool ShowHelp { get; set; }
25 +
26 + private bool SuppressLogo { get; set; }
27 +
28 public ICommandLineCommand CreateCommand(string[] args)
29 {
30 var arguments = this.ServiceProvider.GetService<ICommandLineArguments>();
@@ -49,11 +53,12 @@ namespace WixToolset.Core.CommandLine
53
54 var command = this.Parse(context);
55
52 - if (command.ShowLogo)
56 + if (!this.SuppressLogo && command?.ShowLogo == true)
57 {
58 var branding = this.ServiceProvider.GetService<IWixBranding>();
59 Console.WriteLine(branding.ReplacePlaceholders("[AssemblyProduct] [AssemblyDescription] version [ProductVersion]"));
60 Console.WriteLine(branding.ReplacePlaceholders("[AssemblyCopyright]"));
61 + Console.WriteLine();
62 }
63
64 return command;
@@ -71,7 +76,6 @@ namespace WixToolset.Core.CommandLine
76
77 private ICommandLineCommand Parse(ICommandLineContext context)
78 {
74 - var branding = context.ServiceProvider.GetService<IWixBranding>();
79 var extensions = context.ExtensionManager.GetServices<IExtensionCommandLine>();
80
81 foreach (var extension in extensions)
@@ -86,28 +90,31 @@ namespace WixToolset.Core.CommandLine
90 String.IsNullOrEmpty(parser.ErrorArgument) &&
91 parser.TryGetNextSwitchOrArgument(out var arg))
92 {
89 - if (String.IsNullOrWhiteSpace(arg)) // skip blank arguments.
90 - {
91 - continue;
92 - }
93 -
94 - // First argument must be the command or global switch (that creates a command).
93 + // If we don't have a command yet, try to parse for a command or a global switch.
94 if (command == null)
95 {
97 - if (!this.TryParseCommand(arg, parser, extensions, out command))
96 + if (this.TryParseCommand(arg, parser, extensions, out command))
97 {
98 + // Found our command, all good.
99 + }
100 + else if (!parser.IsSwitch(arg) || !TryParseCommandLineArgumentWithExtension(arg, parser, extensions))
101 + {
102 + // Not a global switch handled by an extension, so failure.
103 parser.ReportErrorArgument(arg);
104 }
105 }
106 else if (parser.IsSwitch(arg))
107 {
104 - if (!command.TryParseArgument(parser, arg) && !TryParseCommandLineArgumentWithExtension(arg, parser, extensions) &&
105 - !this.TryParseStandardCommandLineSwitch(command, parser, arg))
108 + // Commands get first crack at parsing switches then extensions then the standard.
109 + if (!command.TryParseArgument(parser, arg) &&
110 + !TryParseCommandLineArgumentWithExtension(arg, parser, extensions) &&
111 + !this.TryParseStandardCommandLineSwitch(parser, arg))
112 {
113 parser.ReportErrorArgument(arg);
114 }
115 }
110 - else if (!TryParseCommandLineArgumentWithExtension(arg, parser, extensions) && !command.TryParseArgument(parser, arg))
116 + else if (!TryParseCommandLineArgumentWithExtension(arg, parser, extensions) &&
117 + !command.TryParseArgument(parser, arg))
118 {
119 parser.ReportErrorArgument(arg);
120 }
@@ -121,10 +128,15 @@ namespace WixToolset.Core.CommandLine
128 // If we hit an error, do not return a command.
129 if (!String.IsNullOrEmpty(parser.ErrorArgument))
130 {
124 - return null;
131 + command = null;
132 + }
133 + else if (this.ShowHelp || command == null)
134 + {
135 + var branding = context.ServiceProvider.GetService<IWixBranding>();
136 + command = new HelpCommand(extensions, branding, command);
137 }
138
127 - return command ?? new HelpCommand(extensions, branding);
139 + return command;
140 }
141
142 private bool TryParseCommand(string arg, ICommandLineParser parser, IEnumerable<IExtensionCommandLine> extensions, out ICommandLineCommand command)
@@ -141,7 +153,7 @@ namespace WixToolset.Core.CommandLine
153 case "help":
154 case "-help":
155 var branding = this.ServiceProvider.GetService<IWixBranding>();
144 - command = new HelpCommand(extensions, branding);
156 + command = new HelpCommand(extensions, branding, null);
157 break;
158
159 case "version":
@@ -184,7 +196,7 @@ namespace WixToolset.Core.CommandLine
196 return false;
197 }
198
187 - private bool TryParseStandardCommandLineSwitch(ICommandLineCommand command, ICommandLineParser parser, string arg)
199 + private bool TryParseStandardCommandLineSwitch(ICommandLineParser parser, string arg)
200 {
201 var parameter = arg.Substring(1).ToLowerInvariant();
202
@@ -193,11 +205,13 @@ namespace WixToolset.Core.CommandLine
205 case "?":
206 case "h":
207 case "help":
196 - command.ShowHelp = true;
208 + case "-help":
209 + this.ShowHelp = true;
210 return true;
211
212 case "nologo":
200 - command.ShowLogo = false;
213 + case "-nologo":
214 + this.SuppressLogo = true;
215 return true;
216
217 case "v":
src/wix/WixToolset.Core/CommandLine/CommandLineParser.cs
+11 -10
@@ -5,6 +5,7 @@ namespace WixToolset.Core.CommandLine
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8 + using System.Linq;
9 using WixToolset.Data;
10 using WixToolset.Extensibility.Services;
11
@@ -12,19 +13,19 @@ namespace WixToolset.Core.CommandLine
13 {
14 private const string ExpectedArgument = "expected argument";
15
15 - public string ErrorArgument { get; private set; }
16 -
17 - private Queue<string> RemainingArguments { get; }
18 -
19 - private IMessaging Messaging { get; }
20 -
16 public CommandLineParser(IMessaging messaging, string[] arguments, string errorArgument)
17 {
18 this.Messaging = messaging;
24 - this.RemainingArguments = new Queue<string>(arguments);
19 + this.RemainingArguments = new Queue<string>(arguments.Where(a => !String.IsNullOrWhiteSpace(a))); // skip blank arguments.
20 this.ErrorArgument = errorArgument;
21 }
22
23 + public string ErrorArgument { get; private set; }
24 +
25 + private Queue<string> RemainingArguments { get; }
26 +
27 + private IMessaging Messaging { get; }
28 +
29 public bool IsSwitch(string arg)
30 {
31 return !String.IsNullOrEmpty(arg) && '-' == arg[0];
@@ -132,15 +133,15 @@ namespace WixToolset.Core.CommandLine
133 this.ErrorArgument = argument;
134 }
135
135 - public bool TryGetNextSwitchOrArgument(out string arg)
136 + public bool TryGetNextSwitchOrArgument(out string argument)
137 {
138 if (this.RemainingArguments.Count > 0)
139 {
139 - arg = this.RemainingArguments.Dequeue();
140 + argument = this.RemainingArguments.Dequeue();
141 return true;
142 }
143
143 - arg = null;
144 + argument = null;
145 return false;
146 }
147
src/wix/WixToolset.Core/CommandLine/HelpCommand.cs
+87 -39
@@ -11,67 +11,115 @@ namespace WixToolset.Core.CommandLine
11 using WixToolset.Extensibility.Data;
12 using WixToolset.Extensibility.Services;
13
14 - internal class HelpCommand : ICommandLineCommand
14 + internal class HelpCommand : BaseCommandLineCommand
15 {
16 - private static readonly ExtensionCommandLineSwitch[] BuiltInSwitches = new ExtensionCommandLineSwitch[]
17 - {
18 - new ExtensionCommandLineSwitch { Switch = "build", Description = "Build a wixlib, package or bundle." },
19 - new ExtensionCommandLineSwitch { Switch = "decompile", Description = "Decompile a package or bundle into source code." },
20 - };
21 -
22 - public HelpCommand(IEnumerable<IExtensionCommandLine> extensions, IWixBranding branding)
16 + public HelpCommand(IEnumerable<IExtensionCommandLine> extensions, IWixBranding branding, ICommandLineCommand command)
17 {
18 this.Extensions = extensions;
19 this.Branding = branding;
20 + this.Command = command;
21 }
22
28 - public bool ShowHelp
23 + public override bool ShowLogo => true;
24 +
25 + private IEnumerable<IExtensionCommandLine> Extensions { get; }
26 +
27 + private IWixBranding Branding { get; }
28 +
29 + private ICommandLineCommand Command { get; }
30 +
31 + public override CommandLineHelp GetCommandLineHelp()
32 {
30 - get => true;
31 - set { }
33 + return new CommandLineHelp(null, "[command] [options]")
34 + {
35 + Switches = new[]
36 + {
37 + new CommandLineHelpSwitch("--help", "-h", "Show command line help."),
38 + new CommandLineHelpSwitch("--version", "-v", "Display WiX Toolset version in use."),
39 + new CommandLineHelpSwitch("--nologo", "Suppress displaying the logo information."),
40 + },
41 + Commands = new[]
42 + {
43 + new CommandLineHelpCommand("build", "Build a wixlib, package or bundle.")
44 + },
45 + Notes = "Run 'wix [command] -h' for more information on a command."
46 + };
47 }
48
34 - public bool ShowLogo
49 + public override Task<int> ExecuteAsync(CancellationToken _)
50 {
36 - get => true;
37 - set { }
38 - }
51 + var extensionsHelp = this.Extensions.Select(e => e.GetCommandLineHelp()).Where(h => h != null).ToList();
52
40 - public bool StopParsing => true;
53 + var help = this.Command?.GetCommandLineHelp() ?? this.GetCommandLineHelp();
54
42 - private IEnumerable<IExtensionCommandLine> Extensions { get; }
55 + var switches = new List<CommandLineHelpSwitch>();
56 + if (help.Switches != null)
57 + {
58 + switches.AddRange(help.Switches);
59 + }
60
44 - private IWixBranding Branding { get; }
61 + switches.AddRange(extensionsHelp.Where(e => e.Switches != null).SelectMany(e => e.Switches));
62
46 - public Task<int> ExecuteAsync(CancellationToken _)
47 - {
48 - var commandLineSwitches = new List<ExtensionCommandLineSwitch>(BuiltInSwitches);
49 - commandLineSwitches.AddRange(this.Extensions.SelectMany(e => e.CommandLineSwitches).OrderBy(s => s.Switch, StringComparer.Ordinal));
50 -
51 - Console.WriteLine();
52 - Console.WriteLine("Usage: wix [option]");
53 - Console.WriteLine("Usage: wix [command]");
54 - Console.WriteLine();
55 - Console.WriteLine("Options:");
56 - Console.WriteLine(" -h|--help Show command line help.");
57 - Console.WriteLine(" --version Display WiX Toolset version in use.");
58 - Console.WriteLine();
59 -
60 - Console.WriteLine("Commands:");
61 - foreach (var commandLineSwitch in commandLineSwitches)
63 + var commands = new List<CommandLineHelpCommand>();
64 + if (help.Commands != null)
65 + {
66 + commands.AddRange(help.Commands);
67 + }
68 +
69 + if (this.Command == null)
70 + {
71 + commands.AddRange(extensionsHelp.Where(e => e.Commands != null).SelectMany(e => e.Commands));
72 + }
73 +
74 + if (!String.IsNullOrEmpty(help.Description))
75 + {
76 + Console.WriteLine("Description:");
77 + Console.WriteLine(" {0}", help.Description);
78 + Console.WriteLine();
79 + }
80 +
81 + if (!String.IsNullOrEmpty(help.Usage))
82 + {
83 + Console.WriteLine("Usage:");
84 + Console.WriteLine(" wix {0}", help.Usage);
85 + Console.WriteLine();
86 + }
87 +
88 + if (switches.Count > 0)
89 + {
90 + Console.WriteLine("Options:");
91 + foreach (var commandLineSwitch in help.Switches)
92 + {
93 + var switchName = String.IsNullOrEmpty(commandLineSwitch.ShortName) ? commandLineSwitch.Name : $"{commandLineSwitch.ShortName}|{commandLineSwitch.Name}";
94 + Console.WriteLine(" {0,-17} {1}", switchName, commandLineSwitch.Description);
95 + }
96 +
97 + Console.WriteLine();
98 + }
99 +
100 + if (commands.Count > 0)
101 + {
102 + Console.WriteLine("Commands:");
103 + foreach (var command in commands)
104 + {
105 + Console.WriteLine(" {0,-17} {1}", command.Name, command.Description);
106 + }
107 +
108 + Console.WriteLine();
109 + }
110 +
111 + if (!String.IsNullOrEmpty(help.Notes))
112 {
63 - Console.WriteLine(" {0,-17} {1}", commandLineSwitch.Switch, commandLineSwitch.Description);
113 + Console.WriteLine(help.Notes);
114 + Console.WriteLine();
115 }
116
66 - Console.WriteLine();
67 - Console.WriteLine("Run 'wix [command] -h[elp]' for more information on a command.");
68 - Console.WriteLine();
117 Console.WriteLine(this.Branding.ReplacePlaceholders("For more information see: [SupportUrl]"));
118
119 return Task.FromResult(-1);
120 }
121
74 - public bool TryParseArgument(ICommandLineParser parseHelper, string argument)
122 + public override bool TryParseArgument(ICommandLineParser parseHelper, string argument)
123 {
124 return true; // eat any arguments
125 }
src/wix/WixToolset.Core/CommandLine/VersionCommand.cs
+8 -8
@@ -5,18 +5,18 @@ namespace WixToolset.Core.CommandLine
5 using System;
6 using System.Threading;
7 using System.Threading.Tasks;
8 + using WixToolset.Extensibility;
9 using WixToolset.Extensibility.Data;
10 using WixToolset.Extensibility.Services;
11
11 - internal class VersionCommand : ICommandLineCommand
12 + internal class VersionCommand : BaseCommandLineCommand
13 {
13 - public bool ShowHelp { get; set; }
14 -
15 - public bool ShowLogo { get; set; }
16 -
17 - public bool StopParsing => true;
14 + public override CommandLineHelp GetCommandLineHelp()
15 + {
16 + return null;
17 + }
18
19 - public Task<int> ExecuteAsync(CancellationToken cancellationToken)
19 + public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
20 {
21 // $(GitBaseVersionMajor).$(GitBaseVersionMinor).$(GitBaseVersionPatch)$(GitSemVerDashLabel)+$(Commit)
22 Console.WriteLine("{0}.{1}.{2}{3}+{4}", ThisAssembly.Git.BaseVersion.Major
@@ -27,7 +27,7 @@ namespace WixToolset.Core.CommandLine
27 return Task.FromResult(0);
28 }
29
30 - public bool TryParseArgument(ICommandLineParser parseHelper, string argument)
30 + public override bool TryParseArgument(ICommandLineParser parseHelper, string argument)
31 {
32 return true; // eat any arguments
33 }
src/wix/test/Example.Extension/ExamplePreprocessorExtensionAndCommandLine.cs
+7 -2
@@ -3,7 +3,6 @@
3 namespace Example.Extension
4 {
5 using System;
6 - using System.Collections.Generic;
6 using WixToolset.Extensibility;
7 using WixToolset.Extensibility.Data;
8 using WixToolset.Extensibility.Services;
@@ -12,7 +11,13 @@ namespace Example.Extension
11 {
12 private string exampleValueFromCommandLine;
13
15 - public IReadOnlyCollection<ExtensionCommandLineSwitch> CommandLineSwitches => throw new NotImplementedException();
14 + public CommandLineHelp GetCommandLineHelp()
15 + {
16 + return new CommandLineHelp("Example command line extension", "example value", new[]
17 + {
18 + new CommandLineHelpSwitch("-example", "Sets an example value")
19 + });
20 + }
21
22 public ExamplePreprocessorExtensionAndCommandLine()
23 {
src/wix/test/WixToolsetTest.CoreIntegration/CommandLineFixture.cs
+2 -3
@@ -22,10 +22,9 @@ namespace WixToolsetTest.CoreIntegration
22 WixAssert.CompareLineByLine(new[]
23 {
24 "-bindpath is expected to be followed by a value. See -? for additional detail.",
25 - "Additional argument '-bindpath' was unexpected. Remove the argument and add the '-?' switch for more information.",
26 - "No source files specified."
25 + "Additional argument '-bindpath' was unexpected. Remove the argument and add the '-?' switch for more information."
26 }, result.Messages.Select(m => m.ToString()).ToArray());
28 - Assert.Equal(391, result.ExitCode);
27 + Assert.Equal(1, result.ExitCode);
28 }
29
30 [Fact]