.NETアプリケーションからのコンソール出力のキャプチャ(C#)


130

.NETアプリケーションからコンソールアプリケーションを呼び出して、コンソールで生成されたすべての出力をキャプチャするにはどうすればよいですか?

(情報を最初にファイルに保存してから、再公開したくないので、ライブで受け取りたいと思います。)



両方の質問の日付を確認し、どちらが「重複」しているかを確認してください
Gripsoft

「可能性のある重複」は、クリーンアップする方法です。同様の質問を閉じて、最良の回答を保持します。日付は必須ではありません。新しい質問で、最新の回答がある場合でも、重複する質問を閉じるには投票する必要がありますかを参照してください説明が必要であることに同意する場合は、「重複の可能性」自動コメントへの説明リンクの追加に
Michael Freidgeim

回答:


163

これは、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();

3
最後に余分な新しい行が必要ない場合は、Console.Write代わりに使用してください。
tm1 16

2
ReadToEnd()を、ユーザーに入力を求める機能を持つコンソールアプリケーションと組み合わせて使用​​する場合は注意してください。例:ファイルの上書き:YまたはN?etc次に、ReadToEndは、ユーザー入力を待機している間はプロセスが終了しないため、メモリリークが発生する可能性があります。出力をキャプチャするより安全な方法は、process.OutputDataReceivedイベントハンドラーを使用して、受信する出力をアプリケーションに通知することです。
Baaleos、2018年

compiler.StartInfo.FileName = "csc.exe";なので、コードがazure webappにデプロイされている場合にキャプチャする方法。存在しないかもしれません!
Asif Iqbal

compiler.StartInfo.FileName = "csc.exe";なので、コードがazure webappにデプロイされている場合にキャプチャする方法。存在しないかもしれません!
Asif Iqbal

37

これは、@ 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");
}

5
ずっとこれを探してくれてありがとう!
Cバウアー

3
ありがとうございました。これは完璧です。
DrFloyd5

あなたは私のアプリケーションの感謝リストに名誉の場所を得るでしょう。
marsh-wiggle


7

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

2

O2プラットフォーム(オープンソースプロジェクト)にいくつかのヘルパーメソッドを追加しました。これにより、コンソールの出力と入力を介して別のプロセスとの対話を簡単にスクリプト化できます(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/(このブログには、消費方法の詳細も含まれています新しいプロセスのコンソール出力)


それ以来、ConsoleOutを使用するためのサポートを追加しました(この場合、.NETプロセスを自分で開始する場合)。見てください:C#REPLコンソール出力を使用する方法、ネイティブコンソール
Dinis Cruz

2

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


使用例

以下は実行executableargsて印刷されます

  • 白のstdOut
  • 赤のstdErr

コンソールに。

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

1

PythonTRから-PythonProgramcı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

追加されました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)のタイムアウトは機能しません!(コードがハングします!)
S.Serpooshan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.