.NET uygulamamdan bir konsol uygulamasını nasıl çağırırım ve konsolda üretilen tüm çıktıları nasıl yakalayabilirim?
(Unutmayın, bilgileri önce bir dosyaya kaydetmek ve sonra onu canlı olarak almak istediğim için yeniden paylaşmak istemiyorum.)
.NET uygulamamdan bir konsol uygulamasını nasıl çağırırım ve konsolda üretilen tüm çıktıları nasıl yakalayabilirim?
(Unutmayın, bilgileri önce bir dosyaya kaydetmek ve sonra onu canlı olarak almak istediğim için yeniden paylaşmak istemiyorum.)
Yanıtlar:
Bu, ProcessStartInfo.RedirectStandardOutput özelliği kullanılarak oldukça kolay bir şekilde gerçekleştirilebilir . Bağlantılı MSDN belgelerinde tam bir örnek yer almaktadır; tek uyarı, uygulamanızın tüm çıktılarını görmek için standart hata akışını da yeniden yönlendirmeniz gerekebileceğidir.
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
bunun yerine kullanın.
Bu, @mdb'den kabul edilen cevaba göre biraz gelişmedir . Spesifik olarak, sürecin hata çıktısını da alıyoruz. Ek olarak, bu çıktıları olaylar aracılığıyla yakalıyoruz çünkü hem hatayı hem de normal çıktıyı ReadToEnd()
yakalamak istiyorsanız çalışmıyor . Bu işi yapmam biraz zaman aldı çünkü aslında daha sonra aramalar da gerektiriyordu .BeginxxxReadLine()
Start()
Eşzamansız yol:
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");
}
Konsol işleminizi oluştururken çıktıyı yeniden yönlendirmek için ProcessInfo.RedirectStandardOutput kullanın .
Ardından , program çıktısını okumak için Process.StandardOutput'u kullanabilirsiniz .
İkinci bağlantı, nasıl yapılacağına dair örnek bir kod içerir.
ConsoleAppLauncher , bu soruyu yanıtlamak için özel olarak yapılmış açık kaynaklı bir kitaplıktır. Konsolda üretilen tüm çıktıları yakalar ve konsol uygulamasını başlatmak ve kapatmak için basit bir arayüz sağlar.
ConsoleOutput olayı, konsol tarafından standart / hata çıktısına yeni bir satır yazıldığında her seferinde tetiklenir. Satırlar sıraya alınır ve çıktı sırasını takip etmesi garanti edilir.
NuGet paketi olarak da mevcuttur .
Tam konsol çıktısı almak için örnek çağrı:
// Run simplest shell command and return its output.
public static string GetWindowsVersion()
{
return ConsoleApp.Run("cmd", "/c ver").Output.Trim();
}
Canlı geri bildirim ile örnek:
// 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 Platformuna (Açık Kaynak projesi), konsol çıkışı ve girişi aracılığıyla başka bir işlemle etkileşimi kolayca komut dosyası oluşturmanıza olanak tanıyan bir dizi yardımcı yöntem ekledim (bkz. Http://code.google.com/p/o2platform/ source / browse / trunk / O2_Scripts / APIs / Windows / CmdExe / CmdExeAPI.cs )
Ayrıca, geçerli sürecin konsol çıktısının görüntülenmesine izin veren API de sizin için yararlı olabilir (mevcut bir kontrol veya açılır pencerede). Daha fazla ayrıntı için bu blog gönderisine bakın: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (bu blog ayrıca nasıl tüketileceğine ilişkin ayrıntıları da içerir yeni işlemlerin konsol çıktısı)
StdOut ve StdErr için geri aramaları kabul eden reaktif bir sürüm yaptım.
onStdOut
ve
veriler gelir gelmez (işlem çıkmadan önce) onStdErr
eşzamansız
olarak çağrılır .
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);
}
}
Aşağıdakiler executable
ile çalışacak args
ve yazdıracak
konsola.
RunProcess(
executable,
args,
s => { Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(s); },
s => { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(s); }
);
Gönderen Python Programcıları Derneği, e-kitap, Örnek'e - PythonTR :
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
Eklendi process.StartInfo.**CreateNoWindow** = true;
ve 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()
, uygulamanın sonuna kadar bir sonraki ifadeye dönmez. bu yüzden WaitForExit'teki (timeoutMilliseconds) zaman aşımınız çalışmıyor! (kodunuz askıda kalacak!)