2008-10-09 2 views
103

Как вызвать консольное приложение из моего приложения .NET и захватить все выходные данные, созданные на консоли?Захват вывода консоли из приложения .NET (C#)

(Помните, я не хочу, чтобы сохранить информацию в первом файле, а затем повторно выставляю, как я хотел бы получить его в прямом эфире.)

+0

Возможный дубликат [Процесс.начало: как получить выход?] (http://stackoverflow.com/questions/4291912/process-start-how-to-get-the-output) – 2016-10-28 00:26:34

+0

Пожалуйста, просмотрите даты по обоим вопросам и посмотрите, какой из них - duplicate " – Gripsoft 2017-05-30 16:46:01

+0

« Возможный дубликат »- это способ очистки - чтобы закрыть похожие вопросы и сохранить их с лучшими ответами. Дата не является существенной. См. [Должен ли я голосовать, чтобы закрыть дублирующий вопрос, даже если он намного более новый и имеет более современные ответы?] (// meta.stackexchange.com/q/147643) Если вы согласны с тем, что для этого требуется разъяснение, проголосуйте за [Добавить ссылку пояснения к «Возможный дубликат» автоматизированного комментария] (// meta.stackexchange.com/q/281980) – 2017-05-31 00:12:53

ответ

131

Это может быть довольно легко достигается с помощью ProcessStartInfo.RedirectStandardOutput свойства. Полный образец содержится в связанной документации MSDN; единственное предостережение в том, что вам, возможно, придется перенаправить стандартный поток ошибок, а также просмотреть все результаты вашего приложения.

Process compiler = new Process(); 
compiler.StartInfo.FileName = "csc.exe"; 
compiler.StartInfo.Arguments = "/r:System.dll /out:sample.exe stdstr.cs"; 
compiler.StartInfo.UseShellExecute = false; 
compiler.StartInfo.RedirectStandardOutput = true; 
compiler.Start();  

Console.WriteLine(compiler.StandardOutput.ReadToEnd()); 

compiler.WaitForExit(); 
+2

Если вы не хотите, чтобы новая строка была в конце, просто используйте `Console.Write`. – tm1 2016-08-08 11:56:27

+0

Следует отметить, что если вы используете ReadToEnd() в сочетании с консольным приложением, которое может запросить пользователя для ввода. Например: перезаписать файл: Y или N? etc Затем ReadToEnd может привести к утечке памяти, так как процесс никогда не выйдет во время ожидания ввода пользователя. Более безопасный способ захвата вывода - использовать обработчик процесса .OutputDataReceived обработчик события и позволить процессу уведомлять ваше приложение вывода, которое должно быть получено. – Baaleos 2018-05-04 13:45:35

13

Используйте ProcessInfo.RedirectStandardOutput для перенаправления вывода при создании консольного процесса.

Затем вы можете использовать Process.StandardOutput для чтения выходных данных программы.

Вторая ссылка содержит пример кода, как это сделать.

1

От PythonTR - Python Programcıları Derneği, e-kitap, örnek:

Process p = new Process(); // Create new object 
p.StartInfo.UseShellExecute = false; // Do not use shell 
p.StartInfo.RedirectStandardOutput = true; // Redirect output 
p.StartInfo.FileName = "c:\\python26\\python.exe"; // Path of our Python compiler 
p.StartInfo.Arguments = "c:\\python26\\Hello_C_Python.py"; // Path of the .py to be executed 
+1

Можем ли мы перевести это? – 2011-08-12 14:38:05

3

Я добавил ряд вспомогательных методов к (проект Open Source) O2 Platform, которые позволяют легко скрипт взаимодействие с другим процессом через выход консоли и вход (см. http://code.google.com/p/o2platform/source/browse/trunk/O2_Scripts/APIs/Windows/CmdExe/CmdExeAPI.cs)

Также полезным может быть API, который позволяет просматривать вывод консоли текущего процесса (в существующем элементе управления или всплывающем окне). См. Это сообщение в блоге для получения более подробной информации: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (этот блог также содержит сведения о том, как использовать консольный вывод новых процессов)

7

ConsoleAppLauncher - это библиотека с открытым исходным кодом, специально предназначенная для ответа на этот вопрос. Он захватывает все выходные данные, созданные в консоли, и предоставляет простой интерфейс для запуска и закрытия консольного приложения.

Событие ConsoleOutput запускается каждый раз, когда новая строка записывается консолью в стандартный/вывод ошибки. Строки поставлены в очередь и гарантированно соответствуют порядку вывода.

Также доступен как NuGet package.

Пример вызова, чтобы получить полный консольный вывод:

// Run simplest shell command and return its output. 
public static string GetWindowsVersion() 
{ 
    return ConsoleApp.Run("cmd", "/c ver").Output.Trim(); 
} 

образца с живой обратной связи:

// Run ping.exe asynchronously and return roundtrip times back to the caller in a callback 
public static void PingUrl(string url, Action<string> replyHandler) 
{ 
    var regex = new Regex("(time=|Average =)(?<time>.*?ms)", RegexOptions.Compiled); 
    var app = new ConsoleApp("ping", url); 
    app.ConsoleOutput += (o, args) => 
    { 
     var match = regex.Match(args.Line); 
     if (match.Success) 
     { 
      var roundtripTime = match.Groups["time"].Value; 
      replyHandler(roundtripTime); 
     } 
    }; 
    app.Run(); 
} 
2

Добавлено process.StartInfo.**CreateNoWindow** = true; и timeout.

private static void CaptureConsoleAppOutput(string exeName, string arguments, int timeoutMilliseconds, out int exitCode, out string output) 
{ 
    using (Process process = new Process()) 
    { 
     process.StartInfo.FileName = exeName; 
     process.StartInfo.Arguments = arguments; 
     process.StartInfo.UseShellExecute = false; 
     process.StartInfo.RedirectStandardOutput = true; 
     process.StartInfo.CreateNoWindow = true; 
     process.Start(); 

     output = process.StandardOutput.ReadToEnd(); 

     bool exited = process.WaitForExit(timeoutMilliseconds); 
     if (exited) 
     { 
      exitCode = process.ExitCode; 
     } 
     else 
     { 
      exitCode = -1; 
     } 
    } 
} 
15

Это немного улучшилось по сравнению с принятым ответом от @mdb. В частности, мы также фиксируем вывод ошибки процесса. Кроме того, мы записываем эти результаты через события, потому что ReadToEnd() не работает, если вы хотите захватить как ошибку, так и регулярный вывод. Мне потребовалось время, чтобы выполнить эту работу, потому что на самом деле также требуются вызовы BeginxxxReadLine() после Start().

using System.Diagnostics; 

Process process = new Process(); 

void LaunchProcess() 
{ 
    process.EnableRaisingEvents = true; 
    process.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_OutputDataReceived); 
    process.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_ErrorDataReceived); 
    process.Exited += new System.EventHandler(process_Exited); 

    process.StartInfo.FileName = "some.exe"; 
    process.StartInfo.Arguments = "param1 param2" 
    process.StartInfo.UseShellExecute = false; 
    process.StartInfo.RedirectStandardError = true; 
    process.StartInfo.RedirectStandardOutput = true; 

    process.Start(); 
    process.BeginErrorReadLine(); 
    process.BeginOutputReadLine();   

    //below line is optional if we want a blocking call 
    //process.WaitForExit(); 
} 

void process_Exited(object sender, EventArgs e) 
{ 
    Console.WriteLine(string.Format("process exited with code {0}\n", process.ExitCode.ToString())); 
} 

void process_ErrorDataReceived(object sender, DataReceivedEventArgs e) 
{ 
    Console.WriteLine(e.Data + "\n"); 
} 

void process_OutputDataReceived(object sender, DataReceivedEventArgs e) 
{ 
    Console.WriteLine(e.Data + "\n"); 
} 
Смежные вопросы