Як я можу викликати консольну програму з мого додатка .NET і захопити весь вихід, отриманий на консолі?
(Пам'ятайте, я не хочу спочатку зберігати інформацію у файлі, а потім репортаж, як я хотів би отримувати її як живу.)
Як я можу викликати консольну програму з мого додатка .NET і захопити весь вихід, отриманий на консолі?
(Пам'ятайте, я не хочу спочатку зберігати інформацію у файлі, а потім репортаж, як я хотів би отримувати її як живу.)
Відповіді:
Це може бути досить легко досягти за допомогою властивості 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();
Console.Write
замість цього.
Це трохи покращення порівняно з прийнятою відповіддю від @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");
}
Використовуйте ProcessInfo.RedirectStandardOutput для перенаправлення виводу під час створення консольного процесу.
Тоді ви можете використовувати Process.StandardOutput для читання результатів програми.
Друга посилання містить зразок коду, як це зробити.
ConsoleAppLauncher - це бібліотека з відкритим кодом, створена спеціально для відповіді на це питання. Він фіксує весь вихід, отриманий на консолі, та забезпечує простий інтерфейс для запуску та закриття консольного додатка.
Подія ConsoleOutput запускається кожного разу, коли консоль записує новий рядок до стандартного виводу / помилки. Рядки в черзі та гарантовано дотримуються порядку виводу.
Також доступний як пакет NuGet .
Зразок виклику, щоб отримати повний вихід консолі:
// 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();
}
До платформи O2 (проект з відкритим кодом) я додав ряд допоміжних методів, які дозволяють легко скриптувати взаємодію з іншим процесом через консольний вихід та вхід (див. Http://code.google.com/p/o2platform/ source / search / trunk / O2_Scripts / API / Windows / CmdExe / CmdExeAPI.cs )
Також може бути корисним для вас API, який дозволяє переглядати консольний вихід поточного процесу (у наявному вікні управління чи спливаючому вікні). Дивіться цю публікацію в блозі для отримання більш детальної інформації: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (цей блог містить також інформацію про споживання консольний вихід нових процесів)
Я створив реактивну версію, яка приймає зворотні дзвінки для stdOut та StdErr.
onStdOut
і onStdErr
викликаються асинхронно,
як тільки дані надходять (до того, як процес закінчується).
public static Int32 RunProcess(String path,
String args,
Action<String> onStdOut = null,
Action<String> onStdErr = null)
{
var readStdOut = onStdOut != null;
var readStdErr = onStdErr != null;
var process = new Process
{
StartInfo =
{
FileName = path,
Arguments = args,
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = readStdOut,
RedirectStandardError = readStdErr,
}
};
process.Start();
if (readStdOut) Task.Run(() => ReadStream(process.StandardOutput, onStdOut));
if (readStdErr) Task.Run(() => ReadStream(process.StandardError, onStdErr));
process.WaitForExit();
return process.ExitCode;
}
private static void ReadStream(TextReader textReader, Action<String> callback)
{
while (true)
{
var line = textReader.ReadLine();
if (line == null)
break;
callback(line);
}
}
Нижче буде працювати executable
з args
і друку
до консолі.
RunProcess(
executable,
args,
s => { Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(s); },
s => { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(s); }
);
Від 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
Додано 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;
}
}
}
StandardOutput.ReadToEnd()
він не повернеться до наступного оператора до кінця програми. тому час очікування в WaitForExit (timeoutMilliseconds) не працює! (ваш код буде висіти!)