2013-07-07 2 views
2

Я хочу назвать исполняемый файл (в моем случае это PNGOUT.exe) и захватить его вывод из stdout. Но оказалось, что это сложно: приложение использует какие-то управляющие символы для замены ранее напечатанного вывода (отображение прогресса), а классы C# счастливо записывают их, и когда я хочу анализировать выходную строку, у меня появляется серьезная головная боль. (Это даже потребовалось некоторое время для меня, чтобы выяснить, что происходит с моей строкой)Как работать с выводами из консольных приложений, использующих контрольные символы?

Я звоню исполняемый следующим способом:

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

мне нужно либо использовать другой метод, который фиксирует только конечное состояние текста в консоли или каким-то образом избавиться от управляющих символов в result (не просто удалить их, а «применить» их к строке, чтобы получить окончательный вид). Как это можно сделать?

+0

Являются ли управляющие символы экранированными? (например, '\\ t' вместо' \ t')? – keyboardP

+0

Если я просто печатаю строку, она выглядит как окончательный текст, поэтому я думаю, что нет, они не сбегают. –

+1

Если не сбежать, то Base64 может быть закодирован? В основном вам необходимо определить характер вашего ввода. –

ответ

1

Скорее всего, вывод содержит \ r, который просто возвращает курсор к началу текущей строки. Если это так, то вы можете отрегулировать строку соответствующим образом, удалив текущую строку. Это не просто, но вам придется также перезаписать предыдущую строку. Я буду работать над некоторым кодом и посмотреть, смогу ли я найти решение.

EDIT: Вот решение, которое я придумал - это слегка испытанный. Выход будет в переменной lines, которую вы можете либо проанализировать отдельно, либо объединиться для анализа в виде одной строки.

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); 
    } 
} 
+0

\ r - единственный символ, который может вызвать такое поведение? Тогда это может быть немного проще ... –

+0

Это не может быть символ * only *, который может вызвать это поведение, но он, безусловно, наиболее распространен. Я добавил свое решение - он в основном выполняет итерацию по каждой строке «true» и обновляет ее по мере необходимости –

+1

Не забывайте '\ b', очень часто. –

Смежные вопросы