【问题标题】:Execute cmd.exe command (webpack) on windows with .NET Core and preserve colors and output使用 .NET Core 在 Windows 上执行 cmd.exe 命令(webpack)并保留颜色和输出
【发布时间】:2018-04-13 07:14:59
【问题描述】:

如何从 .NET Core - 控制台应用程序执行 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;
}

我的输出:

预期输出:

我发现了 2 个问题: 当我运行命令时

  • 来自 cmd.exe,进度以百分比显示,但正在运行命令 from dotnet 输出奇怪的字符...
  • 颜色缺失

【问题讨论】:

    标签: c# webpack command .net-core command-prompt


    【解决方案1】:

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

    在 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);
    }
    

    如果你在 Windows 10 上运行它,它应该以 magentoo 颜色打印“Hello World”到控制台输出,而不是一些废话。

    因此,如果您在编写重定向输出之前执行此操作 - 它应该可以解决您的问题。

    【讨论】:

    • 谢谢@Evk。这太棒了。你能写出对windows server的支持如何吗?
    • @Makla 我只知道它是在 Windows 10 中添加的(甚至是特定的内部版本号),不知道任何版本的 Windows 服务器是否都支持它。你当然可以试试看效果如何。
    猜你喜欢
    • 2015-11-05
    • 1970-01-01
    • 1970-01-01
    • 2020-03-20
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 2013-07-30
    • 1970-01-01
    相关资源
    最近更新 更多