diff --git a/Source/ChocolateyGui.Common.Windows/ChocolateyGui.Common.Windows.csproj b/Source/ChocolateyGui.Common.Windows/ChocolateyGui.Common.Windows.csproj
index ca795e875..5a96d1e0b 100644
--- a/Source/ChocolateyGui.Common.Windows/ChocolateyGui.Common.Windows.csproj
+++ b/Source/ChocolateyGui.Common.Windows/ChocolateyGui.Common.Windows.csproj
@@ -68,6 +68,8 @@
..\packages\chocolatey.lib.0.10.15\lib\chocolatey.dll
+ False
+ False
..\packages\ControlzEx.4.4.0\lib\net462\ControlzEx.dll
diff --git a/Source/ChocolateyGui.Common/ChocolateyGui.Common.csproj b/Source/ChocolateyGui.Common/ChocolateyGui.Common.csproj
index 40b8bdc3e..2ea24e28f 100644
--- a/Source/ChocolateyGui.Common/ChocolateyGui.Common.csproj
+++ b/Source/ChocolateyGui.Common/ChocolateyGui.Common.csproj
@@ -55,6 +55,8 @@
..\packages\chocolatey.lib.0.10.15\lib\chocolatey.dll
+ False
+ False
..\packages\LiteDB.5.0.5\lib\net45\LiteDB.dll
@@ -187,6 +189,7 @@
+
@@ -222,5 +225,8 @@
+
+
+
\ No newline at end of file
diff --git a/Source/ChocolateyGui.Common/Startup/AssemblyResolver.cs b/Source/ChocolateyGui.Common/Startup/AssemblyResolver.cs
new file mode 100644
index 000000000..d18c64c13
--- /dev/null
+++ b/Source/ChocolateyGui.Common/Startup/AssemblyResolver.cs
@@ -0,0 +1,121 @@
+//
+// Copyright 2017 - Present Chocolatey Software, LLC
+// Copyright 2014 - 2017 Rob Reynolds, the maintainers of Chocolatey, and RealDimensions Software, LLC
+//
+
+using System;
+using System.Linq;
+using System.Reflection;
+using System.Threading;
+using Serilog;
+
+namespace ChocolateyGui.Common.Startup
+{
+ public class AssemblyResolver
+ {
+ private const int LOCKRESOLUTIONTIMEOUTSECONDS = 5;
+ private static readonly object _lockObject = new object();
+
+ public static Assembly ResolveOrReloadChocolateyAssembly(string assemblyFileLocation)
+ {
+ return ResolveOrLoadAssemblyInternal(
+ "chocolatey",
+ string.Empty,
+ assemblyFileLocation,
+ (assembly) =>
+ {
+ var assemblyName = assembly.GetName();
+
+ return string.Equals(assemblyName.Name, "chocolatey", StringComparison.OrdinalIgnoreCase) &&
+ assemblyName.Version != new Version(0, 10, 15, 0); // TODO: Should maybe be created automatically
+ });
+ }
+
+ ///
+ /// Resolves or loads an assembly. If an assembly is already loaded, no need to reload it.
+ ///
+ /// Simple Name of the assembly, such as "chocolatey"
+ /// The public key token.
+ /// The assembly file location. Typically the path to the DLL on disk.
+ /// An assembly
+ /// Unable to enter synchronized code to determine assembly loading
+ public static Assembly ResolveOrLoadAssembly(string assemblySimpleName, string publicKeyToken, string assemblyFileLocation)
+ {
+ return ResolveOrLoadAssemblyInternal(
+ assemblySimpleName,
+ publicKeyToken,
+ assemblyFileLocation,
+ (assembly) => string.Equals(assembly.GetName().Name, assemblySimpleName, StringComparison.OrdinalIgnoreCase));
+ }
+
+ public static bool IsPublicKeyToken(AssemblyName assemblyName, string expectedKeyToken)
+ {
+ var publicKey = GetPublicKeyToken(assemblyName);
+
+ return string.Equals(publicKey, expectedKeyToken, StringComparison.OrdinalIgnoreCase);
+ }
+
+ public static string GetPublicKeyToken(AssemblyName assemblyName)
+ {
+ if (assemblyName == null)
+ {
+ return string.Empty;
+ }
+
+ var publicKeyToken = assemblyName.GetPublicKeyToken();
+
+ if (publicKeyToken == null || publicKeyToken.Length == 0)
+ {
+ return string.Empty;
+ }
+
+ return publicKeyToken.Select(x => x.ToString("x2")).Aggregate((x, y) => x + y);
+ }
+
+ private static Assembly ResolveOrLoadAssemblyInternal(string assemblySimpleName, string publicKeyToken, string assemblyFileLocation, Func assemblyPredicate)
+ {
+ var lockTaken = false;
+ try
+ {
+ Monitor.TryEnter(_lockObject, TimeSpan.FromSeconds(LOCKRESOLUTIONTIMEOUTSECONDS), ref lockTaken);
+ }
+ catch (Exception)
+ {
+ throw new Exception("Unable to enter synchronized code to determine assembly loading");
+ }
+
+ Assembly resolvedAssembly = null;
+ if (lockTaken)
+ {
+ try
+ {
+ foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies().Where(assemblyPredicate))
+ {
+ if (string.IsNullOrWhiteSpace(publicKeyToken) || string.Equals(GetPublicKeyToken(assembly.GetName()), publicKeyToken, StringComparison.OrdinalIgnoreCase))
+ {
+ Log.Debug("Returning loaded assembly type for '{0}'", assemblySimpleName);
+
+ resolvedAssembly = assembly;
+ break;
+ }
+ }
+
+ if (resolvedAssembly == null)
+ {
+ Log.Debug("Loading up '{0}' assembly type from '{1}'", assemblySimpleName, assemblyFileLocation);
+
+ // Reading the raw bytes and calling 'Load' causes an exception, as such we use LoadFrom instead.
+ resolvedAssembly = Assembly.LoadFrom(assemblyFileLocation);
+ }
+ }
+ finally
+ {
+ Monitor.Pulse(_lockObject);
+ Monitor.Exit(_lockObject);
+ }
+ }
+
+ return resolvedAssembly;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/ChocolateyGui/App.xaml.cs b/Source/ChocolateyGui/App.xaml.cs
index d46dbb9cf..fc8d3806f 100644
--- a/Source/ChocolateyGui/App.xaml.cs
+++ b/Source/ChocolateyGui/App.xaml.cs
@@ -6,13 +6,13 @@
// --------------------------------------------------------------------------------------------------------------------
using System;
+using System.IO;
using System.Reflection;
using System.Windows;
using Autofac;
-using chocolatey;
-using chocolatey.infrastructure.registration;
using ChocolateyGui.Common.Enums;
using ChocolateyGui.Common.Services;
+using ChocolateyGui.Common.Startup;
using ChocolateyGui.Common.Windows;
using ChocolateyGui.Common.Windows.Theming;
@@ -32,30 +32,49 @@ public App()
{
var requestedAssembly = new AssemblyName(args.Name);
+ try
+ {
+ if (string.Equals(requestedAssembly.Name, "chocolatey", StringComparison.OrdinalIgnoreCase))
+ {
+ var installDir = Environment.GetEnvironmentVariable("ChocolateyInstall");
+ if (string.IsNullOrEmpty(installDir))
+ {
+ var rootDrive = Path.GetPathRoot(Assembly.GetExecutingAssembly().Location);
+ if (string.IsNullOrEmpty(rootDrive))
+ {
+ return null; // TODO: Maybe return the chocolatey.dll file instead?
+ }
+
+ installDir = Path.Combine(rootDrive, "ProgramData", "chocolatey");
+ }
+
+ var assemblyLocation = Path.Combine(installDir, "choco.exe");
+
+ return AssemblyResolver.ResolveOrLoadAssembly("choco", string.Empty, assemblyLocation);
+ }
+
#if FORCE_CHOCOLATEY_OFFICIAL_KEY
var chocolateyGuiPublicKey = Bootstrapper.OfficialChocolateyPublicKey;
#else
- var chocolateyGuiPublicKey = Bootstrapper.UnofficialChocolateyPublicKey;
+ var chocolateyGuiPublicKey = Bootstrapper.UnofficialChocolateyPublicKey;
#endif
- try
- {
- if (requestedAssembly.get_public_key_token().is_equal_to(chocolateyGuiPublicKey)
- && requestedAssembly.Name.is_equal_to(Bootstrapper.ChocolateyGuiCommonAssemblySimpleName))
+ if (AssemblyResolver.IsPublicKeyToken(requestedAssembly, chocolateyGuiPublicKey)
+ && string.Equals(requestedAssembly.Name, Bootstrapper.ChocolateyGuiCommonAssemblySimpleName, StringComparison.OrdinalIgnoreCase))
{
- return AssemblyResolution.resolve_or_load_assembly(
+ return AssemblyResolver.ResolveOrLoadAssembly(
Bootstrapper.ChocolateyGuiCommonAssemblySimpleName,
- requestedAssembly.get_public_key_token(),
- Bootstrapper.ChocolateyGuiCommonAssemblyLocation).UnderlyingType;
+ AssemblyResolver.GetPublicKeyToken(requestedAssembly),
+ Bootstrapper.ChocolateyGuiCommonAssemblyLocation);
}
- if (requestedAssembly.get_public_key_token().is_equal_to(chocolateyGuiPublicKey)
- && requestedAssembly.Name.is_equal_to(Bootstrapper.ChocolateyGuiCommonWindowsAssemblySimpleName))
+ if (AssemblyResolver.IsPublicKeyToken(requestedAssembly, chocolateyGuiPublicKey)
+ && string.Equals(requestedAssembly.Name, Bootstrapper.ChocolateyGuiCommonWindowsAssemblySimpleName, StringComparison.OrdinalIgnoreCase))
{
- return AssemblyResolution.resolve_or_load_assembly(
+ return AssemblyResolver.ResolveOrLoadAssembly(
Bootstrapper.ChocolateyGuiCommonWindowsAssemblySimpleName,
- requestedAssembly.get_public_key_token(),
- Bootstrapper.ChocolateyGuiCommonWindowsAssemblyLocation).UnderlyingType;
+ AssemblyResolver.GetPublicKeyToken(requestedAssembly),
+ Bootstrapper.ChocolateyGuiCommonWindowsAssemblyLocation);
}
}
catch (Exception ex)
diff --git a/Source/ChocolateyGui/ChocolateyGui.csproj b/Source/ChocolateyGui/ChocolateyGui.csproj
index 634242a84..c1a3d4fe4 100644
--- a/Source/ChocolateyGui/ChocolateyGui.csproj
+++ b/Source/ChocolateyGui/ChocolateyGui.csproj
@@ -99,6 +99,9 @@
..\ChocolateyGuiRules.ruleset
true
+
+ true
+
..\packages\Autofac.4.6.1\lib\net45\Autofac.dll
@@ -117,6 +120,8 @@
..\packages\chocolatey.lib.0.10.15\lib\chocolatey.dll
+ False
+ False
..\packages\ControlzEx.4.4.0\lib\net462\ControlzEx.dll
diff --git a/Source/ChocolateyGuiCli/Bootstrapper.cs b/Source/ChocolateyGuiCli/Bootstrapper.cs
index 42b26d0bd..76f54ce55 100644
--- a/Source/ChocolateyGuiCli/Bootstrapper.cs
+++ b/Source/ChocolateyGuiCli/Bootstrapper.cs
@@ -6,6 +6,7 @@
// --------------------------------------------------------------------------------------------------------------------
using System.IO;
+using System.Reflection;
using Autofac;
using chocolatey.infrastructure.filesystem;
using ChocolateyGui.Common;
@@ -21,7 +22,10 @@ public static class Bootstrapper
private static readonly IFileSystem _fileSystem = new DotNetFileSystem();
#pragma warning disable SA1202
- public static readonly string ChocolateyGuiInstallLocation = _fileSystem.get_directory_name(_fileSystem.get_current_assembly_path());
+
+ // Due to an unknown reason, we can not use chocolateys own get_current_assembly() function here,
+ // as it will be returning the path to the choco.exe executable instead.
+ public static readonly string ChocolateyGuiInstallLocation = _fileSystem.get_directory_name(Assembly.GetExecutingAssembly().CodeBase.Replace("file:///", string.Empty));
public static readonly string ChocolateyInstallEnvironmentVariableName = "ChocolateyInstall";
public static readonly string ChocolateyInstallLocation = System.Environment.GetEnvironmentVariable(ChocolateyInstallEnvironmentVariableName) ?? _fileSystem.get_directory_name(_fileSystem.get_current_assembly_path());
public static readonly string LicensedGuiAssemblyLocation = _fileSystem.combine_paths(ChocolateyInstallLocation, "extensions", "chocolateygui", "chocolateygui.licensed.dll");
diff --git a/Source/ChocolateyGuiCli/ChocolateyGuiCli.csproj b/Source/ChocolateyGuiCli/ChocolateyGuiCli.csproj
index 7606e5ec3..73e419212 100644
--- a/Source/ChocolateyGuiCli/ChocolateyGuiCli.csproj
+++ b/Source/ChocolateyGuiCli/ChocolateyGuiCli.csproj
@@ -57,6 +57,8 @@
..\packages\chocolatey.lib.0.10.15\lib\chocolatey.dll
+ False
+ False
..\packages\LiteDB.5.0.5\lib\net45\LiteDB.dll
@@ -91,8 +93,9 @@
Properties\SolutionInfo.cs
-
+
+
diff --git a/Source/ChocolateyGuiCli/Program.cs b/Source/ChocolateyGuiCli/Program.cs
index ffbe76ad5..1eca0d956 100644
--- a/Source/ChocolateyGuiCli/Program.cs
+++ b/Source/ChocolateyGuiCli/Program.cs
@@ -1,166 +1,82 @@
-// --------------------------------------------------------------------------------------------------------------------
-//
-// Copyright 2017 - Present Chocolatey Software, LLC
-// Copyright 2014 - 2017 Rob Reynolds, the maintainers of Chocolatey, and RealDimensions Software, LLC
+//
+// Copyright 2017 - Present Chocolatey Software, LLC
+// Copyright 2014 - 2017 Rob Reynolds, the maintainers of Chocolatey, and RealDimensions Software, LLC
//
-// --------------------------------------------------------------------------------------------------------------------
using System;
-using System.Collections.Generic;
-using System.Linq;
+using System.IO;
using System.Reflection;
-using System.Text;
-using System.Text.RegularExpressions;
-using Autofac;
-using chocolatey;
-using chocolatey.infrastructure.commandline;
-using chocolatey.infrastructure.registration;
-using ChocolateyGui.Common.Attributes;
-using ChocolateyGui.Common.Commands;
-using ChocolateyGui.Common.Models;
-using ChocolateyGui.Common.Services;
-using LiteDB;
-using Serilog;
-using Assembly = chocolatey.infrastructure.adapters.Assembly;
-using Console = System.Console;
-using GenericRunner = ChocolateyGui.Common.Commands.GenericRunner;
+using ChocolateyGui.Common.Startup;
namespace ChocolateyGuiCli
{
public class Program
{
- private static readonly OptionSet _optionSet = new OptionSet();
private static ResolveEventHandler _handler = null;
- public static OptionSet OptionSet
- {
- get { return _optionSet; }
- }
-
public static void Main(string[] args)
{
- try
- {
- AddAssemblyResolver();
-
- Bootstrapper.Configure();
-
- var commandName = string.Empty;
- IList commandArgs = new List();
-
- // shift the first arg off
- int count = 0;
- foreach (var arg in args)
- {
- if (count == 0)
- {
- count += 1;
- continue;
- }
-
- commandArgs.Add(arg);
- }
+ AddAssemblyResolver();
- var configuration = new ChocolateyGuiConfiguration();
- SetUpGlobalOptions(args, configuration, Bootstrapper.Container);
- SetEnvironmentOptions(configuration);
-
- if (configuration.RegularOutput)
- {
- #if DEBUG
- Bootstrapper.Logger.Warning(" (DEBUG BUILD)".format_with("Chocolatey GUI", configuration.Information.DisplayVersion));
- #else
- Bootstrapper.Logger.Warning("{0}".format_with(configuration.Information.DisplayVersion));
- #endif
+ Runner.Run(args);
+ }
- if (args.Length == 0)
- {
- Bootstrapper.Logger.Information(ChocolateyGui.Common.Properties.Resources.Command_CommandsText.format_with("chocolateyguicli"));
- }
- }
+ #region DupFinder Exclusion
- var runner = new GenericRunner();
- runner.Run(configuration, Bootstrapper.Container, command =>
- {
- ParseArgumentsAndUpdateConfiguration(
- commandArgs,
- configuration,
- (optionSet) => command.ConfigureArgumentParser(optionSet, configuration),
- (unparsedArgs) =>
- {
- command.HandleAdditionalArgumentParsing(unparsedArgs, configuration);
- },
- () =>
- {
- Bootstrapper.Logger.Debug("Performing validation checks...");
- command.HandleValidation(configuration);
- },
- () => command.HelpMessage(configuration));
- });
- }
- catch (Exception ex)
- {
- Bootstrapper.Logger.Error(ex.Message);
- }
- finally
+ private static void AddAssemblyResolver()
+ {
+ _handler = (sender, args) =>
{
- Log.CloseAndFlush();
+ var requestedAssembly = new AssemblyName(args.Name);
- if (Bootstrapper.Container != null)
+ try
{
- if (Bootstrapper.Container.IsRegisteredWithName(Bootstrapper.GlobalConfigurationDatabaseName))
+ if (string.Equals(requestedAssembly.Name, "chocolatey", StringComparison.OrdinalIgnoreCase))
{
- var globalDatabase = Bootstrapper.Container.ResolveNamed(Bootstrapper.GlobalConfigurationDatabaseName);
- globalDatabase.Dispose();
- }
+ var installDir = Environment.GetEnvironmentVariable("ChocolateyInstall");
+ if (string.IsNullOrEmpty(installDir))
+ {
+ var rootDrive = Path.GetPathRoot(Assembly.GetExecutingAssembly().Location);
+ if (string.IsNullOrEmpty(rootDrive))
+ {
+ return null; // TODO: Maybe return the chocolatey.dll file instead?
+ }
- if (Bootstrapper.Container.IsRegisteredWithName(Bootstrapper.UserConfigurationDatabaseName))
- {
- var userDatabase = Bootstrapper.Container.ResolveNamed(Bootstrapper.UserConfigurationDatabaseName);
- userDatabase.Dispose();
- }
+ installDir = Path.Combine(rootDrive, "ProgramData", "chocolatey");
+ }
- Bootstrapper.Container.Dispose();
- }
- }
- }
+ var assemblyLocation = Path.Combine(installDir, "choco.exe");
- #region DupFinder Exclusion
- private static void AddAssemblyResolver()
- {
- _handler = (sender, args) =>
- {
- var requestedAssembly = new AssemblyName(args.Name);
+ return AssemblyResolver.ResolveOrLoadAssembly("choco", string.Empty, assemblyLocation);
+ }
#if FORCE_CHOCOLATEY_OFFICIAL_KEY
- var chocolateyGuiPublicKey = Bootstrapper.OfficialChocolateyPublicKey;
+ var chocolateyGuiPublicKey = Bootstrapper.OfficialChocolateyPublicKey;
#else
- var chocolateyGuiPublicKey = Bootstrapper.UnofficialChocolateyPublicKey;
+ var chocolateyGuiPublicKey = Bootstrapper.UnofficialChocolateyPublicKey;
#endif
- try
- {
- if (requestedAssembly.get_public_key_token().is_equal_to(chocolateyGuiPublicKey)
- && requestedAssembly.Name.is_equal_to(Bootstrapper.ChocolateyGuiCommonAssemblySimpleName))
+ if (AssemblyResolver.IsPublicKeyToken(requestedAssembly, chocolateyGuiPublicKey)
+ && string.Equals(requestedAssembly.Name, Bootstrapper.ChocolateyGuiCommonAssemblySimpleName, StringComparison.OrdinalIgnoreCase))
{
- return AssemblyResolution.resolve_or_load_assembly(
+ return AssemblyResolver.ResolveOrLoadAssembly(
Bootstrapper.ChocolateyGuiCommonAssemblySimpleName,
- requestedAssembly.get_public_key_token(),
- Bootstrapper.ChocolateyGuiCommonAssemblyLocation).UnderlyingType;
+ AssemblyResolver.GetPublicKeyToken(requestedAssembly),
+ Bootstrapper.ChocolateyGuiCommonAssemblyLocation);
}
- if (requestedAssembly.get_public_key_token().is_equal_to(chocolateyGuiPublicKey)
- && requestedAssembly.Name.is_equal_to(Bootstrapper.ChocolateyGuiCommonWindowsAssemblySimpleName))
+ if (AssemblyResolver.IsPublicKeyToken(requestedAssembly, chocolateyGuiPublicKey)
+ && string.Equals(requestedAssembly.Name, Bootstrapper.ChocolateyGuiCommonWindowsAssemblySimpleName, StringComparison.OrdinalIgnoreCase))
{
- return AssemblyResolution.resolve_or_load_assembly(
+ return AssemblyResolver.ResolveOrLoadAssembly(
Bootstrapper.ChocolateyGuiCommonWindowsAssemblySimpleName,
- requestedAssembly.get_public_key_token(),
- Bootstrapper.ChocolateyGuiCommonWindowsAssemblyLocation).UnderlyingType;
+ AssemblyResolver.GetPublicKeyToken(requestedAssembly),
+ Bootstrapper.ChocolateyGuiCommonWindowsAssemblyLocation);
}
}
catch (Exception ex)
{
- Bootstrapper.Logger.Warning("Unable to load Chocolatey GUI assembly. {0}".format_with(ex.Message));
+ Bootstrapper.Logger.Warning("Unable to load Chocolatey GUI assembly. {0}", ex.Message);
}
return null;
@@ -168,145 +84,7 @@ private static void AddAssemblyResolver()
AppDomain.CurrentDomain.AssemblyResolve += _handler;
}
- #endregion
- private static void SetUpGlobalOptions(IList args, ChocolateyGuiConfiguration configuration, IContainer container)
- {
- ParseArgumentsAndUpdateConfiguration(
- args,
- configuration,
- (option_set) =>
- {
- option_set
- .Add(
- "r|limitoutput|limit-output",
- ChocolateyGui.Common.Properties.Resources.Command_LimitOutputOption,
- option => configuration.RegularOutput = option == null);
- },
- (unparsedArgs) =>
- {
- if (!string.IsNullOrWhiteSpace(configuration.CommandName))
- {
- // save help for next menu
- configuration.HelpRequested = false;
- configuration.UnsuccessfulParsing = false;
- }
- },
- () => { },
- () =>
- {
- var commandsLog = new StringBuilder();
- var commands = container.Resolve>();
- foreach (var command in commands.or_empty_list_if_null())
- {
- var attributes = command.GetType().GetCustomAttributes(typeof(LocalizedCommandForAttribute), false).Cast();
- foreach (var attribute in attributes.or_empty_list_if_null())
- {
- commandsLog.AppendFormat(" * {0} - {1}\n", attribute.CommandName, attribute.Description);
- }
- }
-
- Bootstrapper.Logger.Information(ChocolateyGui.Common.Properties.Resources.Command_CommandsListText.format_with("chocolateyguicli"));
- Bootstrapper.Logger.Information(string.Empty);
- Bootstrapper.Logger.Warning(ChocolateyGui.Common.Properties.Resources.Command_CommandsTitle);
- Bootstrapper.Logger.Information(string.Empty);
- Bootstrapper.Logger.Information("{0}".format_with(commandsLog.ToString()));
- Bootstrapper.Logger.Information(ChocolateyGui.Common.Properties.Resources.Command_CommandsText.format_with("chocolateyguicli"));
- Bootstrapper.Logger.Information(string.Empty);
- Bootstrapper.Logger.Warning(ChocolateyGui.Common.Properties.Resources.Command_DefaultOptionsAndSwitches);
- });
- }
-
- private static void SetEnvironmentOptions(ChocolateyGuiConfiguration config)
- {
- var versionService = Bootstrapper.Container.Resolve();
- config.Information.ChocolateyGuiVersion = versionService.Version;
- config.Information.ChocolateyGuiProductVersion = versionService.InformationalVersion;
- config.Information.DisplayVersion = versionService.DisplayVersion;
- config.Information.FullName = Assembly.GetExecutingAssembly().FullName;
- }
-
- private static void ParseArgumentsAndUpdateConfiguration(
- ICollection args,
- ChocolateyGuiConfiguration configuration,
- Action setOptions,
- Action> afterParse,
- Action validateConfiguration,
- Action helpMessage)
- {
- IList unparsedArguments = new List();
-
- // add help only once
- if (_optionSet.Count == 0)
- {
- _optionSet
- .Add(
- "?|help|h",
- ChocolateyGui.Common.Properties.Resources.Command_HelpOption,
- option => configuration.HelpRequested = option != null);
- }
-
- if (setOptions != null)
- {
- setOptions(_optionSet);
- }
-
- try
- {
- unparsedArguments = _optionSet.Parse(args);
- }
- catch (OptionException)
- {
- ShowHelp(_optionSet, helpMessage);
- configuration.UnsuccessfulParsing = true;
- }
-
- // the command argument
- if (string.IsNullOrWhiteSpace(configuration.CommandName) &&
- unparsedArguments.Contains(args.FirstOrDefault()))
- {
- var commandName = args.FirstOrDefault();
- if (!Regex.IsMatch(commandName, @"^[-\/+]"))
- {
- configuration.CommandName = commandName;
- }
- else if (commandName.is_equal_to("-v") || commandName.is_equal_to("--version"))
- {
- // skip help menu
- }
- else
- {
- configuration.HelpRequested = true;
- configuration.UnsuccessfulParsing = true;
- }
- }
-
- if (afterParse != null)
- {
- afterParse(unparsedArguments);
- }
-
- if (configuration.HelpRequested)
- {
- ShowHelp(_optionSet, helpMessage);
- }
- else
- {
- if (validateConfiguration != null)
- {
- validateConfiguration();
- }
- }
- }
-
- private static void ShowHelp(OptionSet optionSet, Action helpMessage)
- {
- if (helpMessage != null)
- {
- helpMessage.Invoke();
- }
-
- optionSet.WriteOptionDescriptions(Console.Out);
- }
+ #endregion DupFinder Exclusion
}
}
\ No newline at end of file
diff --git a/Source/ChocolateyGuiCli/Runner.cs b/Source/ChocolateyGuiCli/Runner.cs
new file mode 100644
index 000000000..b0ce4f33f
--- /dev/null
+++ b/Source/ChocolateyGuiCli/Runner.cs
@@ -0,0 +1,262 @@
+// --------------------------------------------------------------------------------------------------------------------
+//
+// Copyright 2017 - Present Chocolatey Software, LLC
+// Copyright 2014 - 2017 Rob Reynolds, the maintainers of Chocolatey, and RealDimensions Software, LLC
+//
+// --------------------------------------------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+using Autofac;
+using chocolatey;
+using chocolatey.infrastructure.commandline;
+using ChocolateyGui.Common.Attributes;
+using ChocolateyGui.Common.Commands;
+using ChocolateyGui.Common.Models;
+using ChocolateyGui.Common.Services;
+using LiteDB;
+using Serilog;
+using Console = System.Console;
+using GenericRunner = ChocolateyGui.Common.Commands.GenericRunner;
+
+namespace ChocolateyGuiCli
+{
+ public class Runner
+ {
+ private static readonly OptionSet _optionSet = new OptionSet();
+
+ public static OptionSet OptionSet
+ {
+ get { return _optionSet; }
+ }
+
+ public static void Run(string[] args)
+ {
+ try
+ {
+ Bootstrapper.Configure();
+
+ var commandName = string.Empty;
+ IList commandArgs = new List();
+
+ // shift the first arg off
+ var count = 0;
+ foreach (var arg in args)
+ {
+ if (count == 0)
+ {
+ count += 1;
+ continue;
+ }
+
+ commandArgs.Add(arg);
+ }
+
+ var configuration = new ChocolateyGuiConfiguration();
+ SetUpGlobalOptions(args, configuration, Bootstrapper.Container);
+ SetEnvironmentOptions(configuration);
+
+ if (configuration.RegularOutput)
+ {
+#if DEBUG
+ Bootstrapper.Logger.Warning(" (DEBUG BUILD)".format_with("Chocolatey GUI", configuration.Information.DisplayVersion));
+#else
+ Bootstrapper.Logger.Warning("{0}".format_with(configuration.Information.DisplayVersion));
+#endif
+
+ if (args.Length == 0)
+ {
+ Bootstrapper.Logger.Information(ChocolateyGui.Common.Properties.Resources.Command_CommandsText.format_with("chocolateyguicli"));
+ }
+ }
+
+ var runner = new GenericRunner();
+ runner.Run(configuration, Bootstrapper.Container, command =>
+ {
+ ParseArgumentsAndUpdateConfiguration(
+ commandArgs,
+ configuration,
+ (optionSet) => command.ConfigureArgumentParser(optionSet, configuration),
+ (unparsedArgs) =>
+ {
+ command.HandleAdditionalArgumentParsing(unparsedArgs, configuration);
+ },
+ () =>
+ {
+ Bootstrapper.Logger.Debug("Performing validation checks...");
+ command.HandleValidation(configuration);
+ },
+ () => command.HelpMessage(configuration));
+ });
+ }
+ catch (Exception ex)
+ {
+ Bootstrapper.Logger.Error(ex.Message);
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+
+ if (Bootstrapper.Container != null)
+ {
+ if (Bootstrapper.Container.IsRegisteredWithName(Bootstrapper.GlobalConfigurationDatabaseName))
+ {
+ var globalDatabase = Bootstrapper.Container.ResolveNamed(Bootstrapper.GlobalConfigurationDatabaseName);
+ globalDatabase.Dispose();
+ }
+
+ if (Bootstrapper.Container.IsRegisteredWithName(Bootstrapper.UserConfigurationDatabaseName))
+ {
+ var userDatabase = Bootstrapper.Container.ResolveNamed(Bootstrapper.UserConfigurationDatabaseName);
+ userDatabase.Dispose();
+ }
+
+ Bootstrapper.Container.Dispose();
+ }
+ }
+ }
+
+ private static void SetUpGlobalOptions(IList args, ChocolateyGuiConfiguration configuration, IContainer container)
+ {
+ ParseArgumentsAndUpdateConfiguration(
+ args,
+ configuration,
+ (option_set) =>
+ {
+ option_set
+ .Add(
+ "r|limitoutput|limit-output",
+ ChocolateyGui.Common.Properties.Resources.Command_LimitOutputOption,
+ option => configuration.RegularOutput = option == null);
+ },
+ (unparsedArgs) =>
+ {
+ if (!string.IsNullOrWhiteSpace(configuration.CommandName))
+ {
+ // save help for next menu
+ configuration.HelpRequested = false;
+ configuration.UnsuccessfulParsing = false;
+ }
+ },
+ () => { },
+ () =>
+ {
+ var commandsLog = new StringBuilder();
+ var commands = container.Resolve>();
+ foreach (var command in commands.or_empty_list_if_null())
+ {
+ var attributes = command.GetType().GetCustomAttributes(typeof(LocalizedCommandForAttribute), false).Cast();
+ foreach (var attribute in attributes.or_empty_list_if_null())
+ {
+ commandsLog.AppendFormat(" * {0} - {1}\n", attribute.CommandName, attribute.Description);
+ }
+ }
+
+ Bootstrapper.Logger.Information(ChocolateyGui.Common.Properties.Resources.Command_CommandsListText.format_with("chocolateyguicli"));
+ Bootstrapper.Logger.Information(string.Empty);
+ Bootstrapper.Logger.Warning(ChocolateyGui.Common.Properties.Resources.Command_CommandsTitle);
+ Bootstrapper.Logger.Information(string.Empty);
+ Bootstrapper.Logger.Information("{0}".format_with(commandsLog.ToString()));
+ Bootstrapper.Logger.Information(ChocolateyGui.Common.Properties.Resources.Command_CommandsText.format_with("chocolateyguicli"));
+ Bootstrapper.Logger.Information(string.Empty);
+ Bootstrapper.Logger.Warning(ChocolateyGui.Common.Properties.Resources.Command_DefaultOptionsAndSwitches);
+ });
+ }
+
+ private static void SetEnvironmentOptions(ChocolateyGuiConfiguration config)
+ {
+ var versionService = Bootstrapper.Container.Resolve();
+ config.Information.ChocolateyGuiVersion = versionService.Version;
+ config.Information.ChocolateyGuiProductVersion = versionService.InformationalVersion;
+ config.Information.DisplayVersion = versionService.DisplayVersion;
+ config.Information.FullName = Assembly.GetExecutingAssembly().FullName;
+ }
+
+ private static void ParseArgumentsAndUpdateConfiguration(
+ ICollection args,
+ ChocolateyGuiConfiguration configuration,
+ Action setOptions,
+ Action> afterParse,
+ Action validateConfiguration,
+ Action helpMessage)
+ {
+ IList unparsedArguments = new List();
+
+ // add help only once
+ if (_optionSet.Count == 0)
+ {
+ _optionSet
+ .Add(
+ "?|help|h",
+ ChocolateyGui.Common.Properties.Resources.Command_HelpOption,
+ option => configuration.HelpRequested = option != null);
+ }
+
+ if (setOptions != null)
+ {
+ setOptions(_optionSet);
+ }
+
+ try
+ {
+ unparsedArguments = _optionSet.Parse(args);
+ }
+ catch (OptionException)
+ {
+ ShowHelp(_optionSet, helpMessage);
+ configuration.UnsuccessfulParsing = true;
+ }
+
+ // the command argument
+ if (string.IsNullOrWhiteSpace(configuration.CommandName) &&
+ unparsedArguments.Contains(args.FirstOrDefault()))
+ {
+ var commandName = args.FirstOrDefault();
+ if (!Regex.IsMatch(commandName, @"^[-\/+]"))
+ {
+ configuration.CommandName = commandName;
+ }
+ else if (commandName.is_equal_to("-v") || commandName.is_equal_to("--version"))
+ {
+ // skip help menu
+ }
+ else
+ {
+ configuration.HelpRequested = true;
+ configuration.UnsuccessfulParsing = true;
+ }
+ }
+
+ if (afterParse != null)
+ {
+ afterParse(unparsedArguments);
+ }
+
+ if (configuration.HelpRequested)
+ {
+ ShowHelp(_optionSet, helpMessage);
+ }
+ else
+ {
+ if (validateConfiguration != null)
+ {
+ validateConfiguration();
+ }
+ }
+ }
+
+ private static void ShowHelp(OptionSet optionSet, Action helpMessage)
+ {
+ if (helpMessage != null)
+ {
+ helpMessage.Invoke();
+ }
+
+ optionSet.WriteOptionDescriptions(Console.Out);
+ }
+ }
+}
\ No newline at end of file