从 .NET 应用程序捕获控制台输出 (C#)

本文关键字:输出 控制台 NET 应用程序 | 更新日期: 2023-09-27 17:47:22

如何从 .NET 应用程序调用控制台应用程序并捕获控制台中生成的所有输出?

(请记住,我不想先将信息保存在文件中,然后再重新列出,因为我希望将其作为实时接收。

从 .NET 应用程序捕获控制台输出 (C#)

这可以使用 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();

@mdb接受的答案有所改进。具体来说,我们还捕获进程的错误输出。此外,我们通过事件捕获这些输出,因为如果要同时捕获错误和常规输出ReadToEnd()则不起作用。我花了一段时间来完成这项工作,因为它实际上还需要Start()BeginxxxReadLine()电话。

异步方式:

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

使用 ProcessStartInfo.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/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/(此博客还包含有关如何使用新进程的控制台输出的详细信息)

我做了一个反应式版本,接受stdOut和StdErr的回调。
onStdOutonStdErr是异步调用的,
一旦数据到达(在进程退出之前)。

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


示例用法

以下内容将使用args和打印executable运行

  • 白色标准输出
  • 红色标准错误

到控制台。

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