Mengambil keluaran konsol dari aplikasi .NET (C #)

130

Bagaimana cara menjalankan aplikasi konsol dari aplikasi .NET saya dan menangkap semua output yang dihasilkan di konsol?

(Ingat, saya tidak ingin menyimpan informasi terlebih dahulu dalam file dan kemudian mendaftar ulang karena saya ingin menerimanya sebagai siaran langsung.)

Gripsoft
sumber
Kemungkinan duplikat dari Process.start: bagaimana cara mendapatkan output?
Michael Freidgeim
Silakan lihat tanggal pada kedua pertanyaan dan lihat mana yang "duplikat"
Gripsoft
"Kemungkinan duplikat" adalah cara untuk membersihkan - untuk menutup pertanyaan serupa dan menyimpannya dengan jawaban terbaik. Tanggal tidak penting. Lihat Haruskah saya memilih untuk menutup pertanyaan duplikat, meskipun jauh lebih baru, dan memiliki lebih banyak jawaban terkini? Jika Anda setuju bahwa itu memerlukan klarifikasi, silakan pilih tautan Tambah klarifikasi ke komentar otomatis "Kemungkinan duplikat"
Michael Freidgeim

Jawaban:

163

Ini dapat dengan mudah dicapai menggunakan properti ProcessStartInfo.RedirectStandardOutput . Sampel lengkap terdapat dalam dokumentasi MSDN tertaut; satu-satunya peringatan adalah bahwa Anda mungkin harus mengarahkan aliran kesalahan standar juga untuk melihat semua output aplikasi Anda.

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();
mdb
sumber
3
Jika Anda tidak ingin baris baru tambahan di akhir, gunakan Console.Writesaja.
tm1
2
Perlu dicatat bahwa jika Anda menggunakan ReadToEnd () dalam kombinasi dengan aplikasi konsol yang memiliki kemampuan untuk meminta input dari pengguna. Misalnya: Timpa File: Y atau N? dll. Kemudian ReadToEnd dapat menyebabkan kebocoran memori, karena proses tidak pernah keluar saat menunggu input pengguna. Cara yang lebih aman untuk menangkap output adalah dengan menggunakan proses.OutputDataReceived event handler dan biarkan proses memberitahukan aplikasi Anda output yang akan diterima.
Baaleos
Cara menangkap jika seandainya kode tersebut digunakan untuk azure webapp, sejak compiler.StartInfo.FileName = "csc.exe"; mungkin tidak ada!
Asif Iqbal
Cara menangkap jika seandainya kode tersebut digunakan untuk azure webapp, sejak compiler.StartInfo.FileName = "csc.exe"; mungkin tidak ada!
Asif Iqbal
37

Ini sedikit lebih baik dari jawaban yang diterima dari @mdb . Secara khusus, kami juga menangkap output kesalahan dari proses. Selain itu, kami menangkap keluaran ini melalui acara karena ReadToEnd()tidak berfungsi jika Anda ingin menangkap kedua kesalahan dan output biasa. Butuh waktu untuk membuat pekerjaan ini karena sebenarnya juga memerlukan BeginxxxReadLine()panggilan setelah Start().

Cara asinkron:

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");
}
Shital Shah
sumber
5
Terima kasih, sudah mencari ini sejak lama!
C Bauer
3
Terima kasih. Ini sempurna.
DrFloyd5
1
Anda akan mendapatkan tempat terhormat di daftar terima kasih atas aplikasi saya.
marsh-goyangkan
7

ConsoleAppLauncher adalah pustaka sumber terbuka yang dibuat khusus untuk menjawab pertanyaan itu. Ini menangkap semua output yang dihasilkan di konsol dan menyediakan antarmuka sederhana untuk memulai dan menutup aplikasi konsol.

Acara ConsoleOutput dipecat setiap kali ketika baris baru ditulis oleh konsol ke output standar / kesalahan. Garis-garis antrian dan dijamin untuk mengikuti urutan keluaran.

Juga tersedia sebagai paket NuGet .

Contoh panggilan untuk mendapatkan output konsol penuh:

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

Sampel dengan umpan balik langsung:

// 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();
}
SlavaGu
sumber
2

Saya telah menambahkan sejumlah metode pembantu ke Platform O2 (proyek Sumber Terbuka) yang memungkinkan Anda dengan mudah membuat skrip interaksi dengan proses lain melalui output dan input konsol (lihat http://code.google.com/p/o2platform/ source / browse / trunk / O2_Scripts / APIs / Windows / CmdExe / CmdExeAPI.cs )

Juga bermanfaat bagi Anda mungkin API yang memungkinkan tampilan output konsol dari proses saat ini (dalam kontrol yang ada atau jendela sembulan). Lihat posting blog ini untuk detail lebih lanjut: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (blog ini juga berisi detail tentang cara mengonsumsi output konsol dari proses baru)

Dinis Cruz
sumber
Sejak itu saya telah menambahkan lebih banyak dukungan untuk menggunakan ConsoleOut (dalam hal ini jika Anda memulai proses .NET diri Anda). Lihatlah: Cara menggunakan keluaran Konsol di C # REPL , Menambahkan 'Konsol Keluar' ke VisualStudio IDE sebagai Jendela asli , Melihat pesan 'Konsol Keluar' yang dibuat di dalam UserControls
Dinis Cruz
2

Saya membuat versi reaktif yang menerima panggilan balik untuk stdOut dan StdErr.
onStdOutdan onStdErrdipanggil secara tidak sinkron,
segera setelah data tiba (sebelum proses keluar).

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


Contoh penggunaan

Berikut ini akan berjalan executabledengan argsdan dicetak

  • stdOut dalam warna putih
  • stdErr berwarna merah

ke konsol.

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

Dari PythonTR - Python Programcıları Derneği, e-kitap, yang disediakan :

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
livetogogo
sumber
1

Ditambahkan process.StartInfo.**CreateNoWindow** = true;dan 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;
        }
    }
}
Sergei Zinovyev
sumber
Ketika Anda menggunakannya StandardOutput.ReadToEnd()tidak akan kembali ke pernyataan berikutnya sampai akhir aplikasi. jadi batas waktu Anda di WaitForExit (timeoutMilliseconds) tidak berfungsi! (kode Anda akan hang!)
S.Serpooshan