|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace Microsoft.Arcade.Common
{
public class CommandFactory : ICommandFactory
{
public ICommand Create(string executable, params string[] args)
{
return Create(executable, ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args));
}
public ICommand Create(string executable, IEnumerable<string> args)
{
return Create(executable, ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args));
}
public ICommand Create(string executable, string args)
{
ResolveExecutablePath(ref executable, ref args);
return new Command(executable, args);
}
private static void ResolveExecutablePath(ref string executable, ref string args)
{
// On Windows, we want to avoid using "cmd" if possible (it mangles the colors, and a bunch of other things)
// So, do a quick path search to see if we can just directly invoke it
var useCmd = ShouldUseCmd(executable);
if (useCmd)
{
var comSpec = System.Environment.GetEnvironmentVariable("ComSpec");
// cmd doesn't like "foo.exe ", so we need to ensure that if
// args is empty, we just run "foo.exe"
if (!string.IsNullOrEmpty(args))
{
executable = (executable + " " + args).Replace("\"", "\\\"");
}
args = $"/C \"{executable}\"";
executable = comSpec;
}
}
private static bool ShouldUseCmd(string executable)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var extension = Path.GetExtension(executable);
if (!string.IsNullOrEmpty(extension))
{
return !string.Equals(extension, ".exe", StringComparison.Ordinal);
}
else if (executable.Contains(Path.DirectorySeparatorChar))
{
// It's a relative path without an extension
if (File.Exists(executable + ".exe"))
{
// It refers to an exe!
return false;
}
}
else
{
// Search the path to see if we can find it
foreach (var path in System.Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator))
{
var candidate = Path.Combine(path, executable + ".exe");
if (File.Exists(candidate))
{
// We found an exe!
return false;
}
}
}
// It's a non-exe :(
return true;
}
// Non-windows never uses cmd
return false;
}
}
}
|