using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
#if NETCOREAPP3_1_OR_GREATER
using System.Runtime.InteropServices;
#endif
namespace Amazon.Common.DotNetCli.Tools
{
public abstract class AbstractCLIWrapper
{
protected string _workingDirectory;
protected IToolLogger _logger;
public AbstractCLIWrapper(IToolLogger logger, string workingDirectory)
{
this._logger = logger;
this._workingDirectory = workingDirectory;
}
protected int ExecuteCommand(ProcessStartInfo startInfo, string loggerLabel)
{
var handler = (DataReceivedEventHandler)((o, e) =>
{
if (string.IsNullOrEmpty(e.Data))
return;
_logger?.WriteLine($"... {loggerLabel}: " + e.Data);
});
int exitCode;
using (var proc = new Process())
{
proc.StartInfo = startInfo;
proc.Start();
if(startInfo.RedirectStandardOutput)
{
proc.ErrorDataReceived += handler;
proc.OutputDataReceived += handler;
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
proc.EnableRaisingEvents = true;
}
proc.WaitForExit();
exitCode = proc.ExitCode;
}
return exitCode;
}
///
/// A collection of known paths for common utilities that are usually not found in the path
///
static readonly IDictionary KNOWN_LOCATIONS = new Dictionary(StringComparer.OrdinalIgnoreCase)
{
{"dotnet.exe", @"C:\Program Files\dotnet\dotnet.exe" },
{"chmod", @"/bin/chmod" },
{"zip", @"/usr/bin/zip" },
{"docker.exe", @"C:\Program Files\Docker\Docker\Resources\bin\docker.exe" }
};
///
/// Search the path environment variable for the command given.
///
/// The command to search for in the path
/// The full path to the command if found otherwise it will return null
public static string FindExecutableInPath(string command)
{
if (File.Exists(command))
return Path.GetFullPath(command);
#if NETCOREAPP3_1_OR_GREATER
if (string.Equals(command, "dotnet.exe"))
{
if(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
command = "dotnet";
}
var mainModule = Process.GetCurrentProcess().MainModule;
if (!string.IsNullOrEmpty(mainModule?.FileName)
&& Path.GetFileName(mainModule.FileName).Equals(command, StringComparison.OrdinalIgnoreCase))
{
return mainModule.FileName;
}
}
#endif
Func quoteRemover = x =>
{
if (x.StartsWith("\""))
x = x.Substring(1);
if (x.EndsWith("\""))
x = x.Substring(0, x.Length - 1);
return x;
};
var envPath = Environment.GetEnvironmentVariable("PATH");
foreach (var path in envPath.Split(Path.PathSeparator))
{
try
{
var fullPath = Path.Combine(quoteRemover(path), command);
if (File.Exists(fullPath))
return fullPath;
}
catch (Exception)
{
// Catch exceptions and continue if there are invalid characters in the user's path.
}
}
if (KNOWN_LOCATIONS.ContainsKey(command) && File.Exists(KNOWN_LOCATIONS[command]))
return KNOWN_LOCATIONS[command];
return null;
}
}
}