File: CommandFactory\CommandResolution\WindowsExePreferredCommandSpecFactory.cs
Web Access
Project: ..\..\..\src\Cli\dotnet\dotnet.csproj (dotnet)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
#nullable disable
 
using Microsoft.DotNet.Cli.Utils;
 
namespace Microsoft.DotNet.Cli.CommandFactory.CommandResolution;
 
public class WindowsExePreferredCommandSpecFactory : IPlatformCommandSpecFactory
{
    public CommandSpec CreateCommandSpec(
       string commandName,
       IEnumerable<string> args,
       string commandPath,
       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)
            : CreateCommandSpecFromExecutable(commandPath, args);
    }
 
    private static CommandSpec CreateCommandSpecFromExecutable(
        string command,
        IEnumerable<string> args)
    {
        var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args);
        return new CommandSpec(command, escapedArgs);
    }
 
    private static CommandSpec CreateCommandSpecWrappedWithCmd(
        string command,
        IEnumerable<string> args)
    {
        var comSpec = Environment.GetEnvironmentVariable("ComSpec") ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "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.IsSurroundedWithQuotes(command) // Don't quote already quoted strings
            && ArgumentEscaper.ShouldSurroundWithQuotes(command))
        {
            command = $"\"{command}\"";
        }
 
        var escapedArgString = $"/s /c \"{command} {cmdEscapedArgs}\"";
 
        return new CommandSpec(comSpec, escapedArgString);
    }
}