How to deal with output from console applications

2019-05-23 14:38发布

I want to call an executable (in my case, this is PNGOUT.exe) and grab its output from stdout. But it turned out to be tricky - the application uses some sort of control characters to replace previously printed output (display of progress), and C# classes happily record them and when I want to analyze the output string, I get serious headache. (It even took a while for me to figure out what's happening with my string)

I'm calling executable with following method:

public static string RunPNGOut(string pngOutPath, string target) {
   var process = new Process {
      StartInfo = {
         UseShellExecute = false,
         RedirectStandardOutput = true,
         CreateNoWindow = true,
         FileName = pngOutPath,
         Arguments = '"' + target + '"'
      }
   };
   process.Start();

   var result = process.StandardOutput.ReadToEnd();

   process.WaitForExit();

   return result;
}

I need either use different method that captures only final state of text in console, or somehow get rid of control characters in result(not simply delete them, but "apply" them to string to achieve the final look). How can it be done?

1条回答
来,给爷笑一个
2楼-- · 2019-05-23 15:05

Most likely, the output contains \r, which simply returns the cursor to the beginning of the current line. If that's true, then you can adjust the string accordingly by erasing the current line. It's not simple, though - you have to also overwrite the previous line. I'll work on some code and see if I can arrive at a solution.

EDIT: Here's the solution I came up with - it's lightly tested. The output will be in the lines variable, which you can either analyze individually or join together to analyze as a single line.

string rawOut = "Results:\r\n___ % done\r 10\r 20\r 30\r\nError!";
string[] lines = Regex.Split(rawOut, Environment.NewLine);
for(int j=0; j<lines.Length; j++)
{
    string line = lines[j];
    if (line.Contains('\r'))
    {
        string[] subLines = line.Split('\r');
        char[] mainLine = subLines[0].ToCharArray();
        for(int i=1; i<subLines.Length; i++)
        {
            string subLine = Regex.Replace(subLines[i], ".\x0008(.)", "$1");
            if (subLine.Length > mainLine.Length) mainLine = subLine.ToCharArray();
            else subLine.CopyTo(0, mainLine, 0, subLine.Length);
        }
        lines[j] = new String(mainLine);
    }
}
查看更多
登录 后发表回答