C# 在具有.NET内核的windows上执行cmd.exe命令(webpack),并保留颜色和输出

C# 在具有.NET内核的windows上执行cmd.exe命令(webpack),并保留颜色和输出,c#,webpack,command,.net-core,command-prompt,C#,Webpack,Command,.net Core,Command Prompt,如何从.NET Core-console应用程序执行cmd命令(webpack)并保留颜色 这是我当前的代码: static void Main(string[] args) { var dir = args.First(); //build:vendor -> webpack --config webpack.config.vendor.js --progress --color --display-error-details Console.WriteLine(

如何从.NET Core-console应用程序执行cmd命令(
webpack
)并保留颜色

这是我当前的代码:

static void Main(string[] args)
{
    var dir = args.First();
    //build:vendor -> webpack --config webpack.config.vendor.js --progress --color --display-error-details
    Console.WriteLine("npm run build:vendor -- --env.prod".Execute(dir));
    Console.ReadKey();
}

public static string Execute(this string cmd, string startDir)
{
    var process = new Process()
    {
        StartInfo = new ProcessStartInfo
        {
            FileName = "cmd.exe",
            Arguments = $"/c {cmd}",
            RedirectStandardOutput = true,
            UseShellExecute = false,
            CreateNoWindow = true,
            WorkingDirectory = startDir
        }
    };
    process.Start();
    string result = process.StandardOutput.ReadToEnd();
    process.WaitForExit();
    return result;
}
我的输出:

预期产出:

我看到两个问题: 当我运行命令时

  • 在cmd.exe中,进度以百分比显示,但正在运行命令 从dotnet输出奇怪的字符
  • 颜色不见了

从您的屏幕截图上看,它似乎是您的工具用来格式化输出的。这些是字符序列,由支持它们的终端通过命令而不是常规文本来解释

在Windows 10之前,cmd.exe不支持此类代码,而是要求使用特定的winapi函数来控制控制台文本颜色和其他属性。从Windows 10开始,它受支持,但必须启用

例如,假设您这样做:

Console.WriteLine("\x1b[35mHello World\x1b[0m");
默认情况下,它将打印一些与当前输出类似的废话。现在让我们启用对ANSI转义码的支持。为此,我们需要pinvoke到winapi函数
SetConsoleMode

[DllImport("kernel32.dll")]
static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
并使用一些帮助器winapi函数:

[DllImport("kernel32.dll")]
static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
现在我们可以启用所需的标志:

public class Program {
    static void Main(string[] args) {
        const int STD_OUTPUT_HANDLE = -11;
        // get handle to console output
        IntPtr hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        if (hOut != IntPtr.Zero) {
            uint mode;
            // get current mode
            if (GetConsoleMode(hOut, out mode)) {
                // add ENABLE_VIRTUAL_TERMINAL_PROCESSING flag which enables support for ANSI escape codes
                mode |= 0x0004; // ENABLE_VIRTUAL_TERMINAL_PROCESSING flag
                SetConsoleMode(hOut, mode);
            }
        }

        Console.WriteLine("\x1b[35mHello World\x1b[0m");            
    }

    [DllImport("kernel32.dll")]
    static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);

    [DllImport("kernel32.dll")]
    static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr GetStdHandle(int nStdHandle);
}
如果您在Windows10上运行此功能,它应该以magentoo颜色打印“Hello World”以显示控制台输出,而不是胡说八道


因此,如果您在编写重定向输出之前这样做,应该可以解决您的问题。

谢谢@Evk。这太棒了。你能写一下对windows server的支持情况吗?@Makla我所知道的是,它是在windows 10中添加的(甚至是特定的内部版本号),我不知道它是否在任何版本的windows server上都受支持。你当然可以试着看看它是怎么回事。