// Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace Microsoft.DotNet.Cli.Utils { public class WindowsExePreferredCommandSpecFactory : IPlatformCommandSpecFactory { public CommandSpec CreateCommandSpec( string commandName, IEnumerable args, string commandPath, CommandResolutionStrategy resolutionStrategy, IEnvironmentProvider environment) { var useCmdWrapper = false; if (Path.GetExtension(commandPath).Equals(".cmd", StringComparison.OrdinalIgnoreCase)) { var preferredCommandPath = environment.GetCommandPath(commandName, ".exe"); if (preferredCommandPath == null) { useCmdWrapper = true; } else { commandPath = preferredCommandPath; } } return useCmdWrapper ? CreateCommandSpecWrappedWithCmd(commandPath, args, resolutionStrategy) : CreateCommandSpecFromExecutable(commandPath, args, resolutionStrategy); } private CommandSpec CreateCommandSpecFromExecutable( string command, IEnumerable args, CommandResolutionStrategy resolutionStrategy) { var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args); return new CommandSpec(command, escapedArgs, resolutionStrategy); } private CommandSpec CreateCommandSpecWrappedWithCmd( string command, IEnumerable args, CommandResolutionStrategy resolutionStrategy) { var comSpec = Environment.GetEnvironmentVariable("ComSpec") ?? "cmd.exe"; // Handle the case where ComSpec is already the command if (command.Equals(comSpec, StringComparison.OrdinalIgnoreCase)) { command = args.FirstOrDefault(); args = args.Skip(1); } var cmdEscapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForCmdProcessStart(args); if (ArgumentEscaper.ShouldSurroundWithQuotes(command)) { command = $"\"{command}\""; } var escapedArgString = $"/s /c \"{command} {cmdEscapedArgs}\""; return new CommandSpec(comSpec, escapedArgString, resolutionStrategy); } } }