Bir .NET uygulamasından (C #) konsol çıktısını yakalama


130

.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.)



Lütfen her iki sorudaki tarihlere bakın ve hangisinin "yinelenen"
olduğuna bakın

"Olası yineleme", benzer soruları kapatmanın ve en iyi yanıtları içeren birini tutmanın bir yoludur. Tarih önemli değildir. Daha yeni olmasına ve daha güncel yanıtları olmasına rağmen yinelenen bir soruyu kapatmak için oy kullanmalı mıyım? Açıklama gerektirdiğini kabul ediyorsanız, lütfen "Muhtemel çoğaltma" otomatik açıklamasına açıklama bağlantısı ekle'ye
Michael Freidgeim

Yanıtlar:


163

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();

3
Sonunda ekstra yeni satır istemiyorsanız, Console.Writebunun yerine kullanın.
tm1

2
ReadToEnd () 'yi kullanıcıdan giriş için uyarma yeteneğine sahip bir konsol uygulamasıyla birlikte kullanırsanız not edilmelidir. Örneğin: Dosyanın Üzerine Yaz: E veya N? etc Sonra ReadToEnd bir bellek sızıntısına neden olabilir, çünkü işlem kullanıcı girdisini beklerken asla çıkmaz. Çıktı yakalamanın daha güvenli yolu, process.OutputDataReceived olay işleyicisini kullanmak ve işlemin, alınacak çıktıyı uygulamanıza bildirmesine izin vermektir.
Baaleos

Compiler.StartInfo.FileName = "csc.exe" olduğundan, kodun Azure webapp'a dağıtılması durumunda nasıl yakalanır; mevcut olmayabilir!
Asif Iqbal

Compiler.StartInfo.FileName = "csc.exe" olduğundan, kodun Azure webapp'a konuşlandırılması durumunda nasıl yakalanır; mevcut olmayabilir!
Asif Iqbal

37

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

5
Teşekkürler, bunu yıllardır arıyorduk!
C Bauer

3
Teşekkür ederim. Bu harika.
DrFloyd5

1
Başvurumun teşekkür listesinde bir onur yeri alacaksınız.
marsh-wiggle


7

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

2

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ı)


O zamandan beri ConsoleOut'u kullanmak için daha fazla destek ekledim (bu durumda .NET işlemini kendiniz başlatırsanız). : Bir göz atın C # Repl içinde Konsol çıkışını nasıl kullanılır , bir yerli Window olarak Visual Studio IDE 'Konsol Out' ekleme , UserControls içinde oluşturulan 'Konsol Out' mesajlarını görüntüleme
Dinis Cruz

2

StdOut ve StdErr için geri aramaları kabul eden reaktif bir sürüm yaptım.
onStdOutve veriler gelir gelmez (işlem çıkmadan önce) onStdErreş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);
        }
    }


Örnek kullanım

Aşağıdakiler executableile çalışacak argsve yazdıracak

  • stdOut beyaz
  • stdErr kırmızı

konsola.

RunProcess(
    executable,
    args,
    s => { Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(s); },
    s => { Console.ForegroundColor = ConsoleColor.Red;   Console.WriteLine(s); } 
);

1

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

1

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

Kullandığınızda 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!)
S.Serpooshan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.