我正在尝试使用颜色信息捕获控制台应用程序的输出。
如果控制台应用程序使用 ANSI 代码,我的代码处理它没问题。
但是我尝试运行的一些控制台应用程序会丢失颜色信息。
我到处寻找解决方案,但到目前为止,一无所获。
调用代码如下:
si.FileName = @"<A Consola APP>";
si.Arguments = "status";
si.EnvironmentVariables["TERM"] = "xterm";
si.WindowStyle = ProcessWindowStyle.Hidden;
si.CreateNoWindow = true;
si.UseShellExecute = false;
si.RedirectStandardError = true;
si.RedirectStandardOutput = true;
si.StandardErrorEncoding = Encoding.GetEncoding("IBM437");
si.StandardOutputEncoding = Encoding.GetEncoding("IBM437");
proc.ErrorDataReceived += ConsoleDataReceived;
proc.OutputDataReceived += ConsoleDataReceived;
proc.EnableRaisingEvents = true;
proc.Start();
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
这是从控制台应用程序处理 STDOUT 的部分:
/// <summary>
/// Processes the text received from the console.
/// </summary>
/// <param name="sender">The object that raised the event.</param>
/// <param name="e">The <see cref="DataReceivedEventArgs"/> that contains the data of the event.</param>
private void ConsoleDataReceived(object sender, DataReceivedEventArgs e)
{
/*
* Processes the text received from the console in a thread-safe manner.
*/
this.InvokeEx(f => AddANSIText(e.Data + "\n"));
}
private void AddANSIText(string ansiText)
{
try
{
var pos = 0; // the current position in the ANSI text
var fg = TextTerminal.ForeColor; // the default ForeColor
var bg = TextTerminal.BackColor; // the default BackColor
var ms = rxANSICode.Matches(ansiText); // all the ANSI codes in the text.
foreach (Match match in ms)
{
/*
* Appends the block of text prior
* to the current ANSI color code
*/
var block = ansiText.Substring(pos, match.Index - pos);
TextTerminal.AppendText(block, fg, bg);
pos = match.Index + match.Length;
/*
* Gets the ANSI color code
*/
var code = match.Groups["code"].Value;
if (code == "0")
{
/*
* The ANSI color code "0" is a reset
*/
fg = TextTerminal.ForeColor;
bg = TextTerminal.BackColor;
continue;
}
/*
* Gets the specified colors from the code
*/
fg = GetColorFromCode(code, fg, ANSI_FG_Color);
bg = GetColorFromCode(code, fg, ANSI_BG_Color);
}
/*
* Processes any text remaining.
*/
if (pos < ansiText.Length)
{
var block = ansiText.Substring(pos);
TextTerminal.AppendText(block, fg, bg);
}
}
catch (Exception)
{
throw;
}
}
private Color GetColorFromCode(string code, Color currentColor, string[] ansiPalette)
{
/*
* If the color code isn't in the ANSI palette
* returns the current color
*/
var pos = Array.IndexOf(ansiPalette, code);
Debug.WriteLine($"ANSI color code: {code} -- position in the palette: {pos}");
if (pos == -1)
return currentColor;
/*
* Returns the color from the palette
*/
return palette[pos];
}