Chụp đầu ra giao diện điều khiển từ ứng dụng .NET (C #)


130

Làm cách nào để gọi ứng dụng bảng điều khiển từ ứng dụng .NET của tôi và nắm bắt tất cả đầu ra được tạo trong bảng điều khiển?

(Hãy nhớ rằng, tôi không muốn lưu thông tin trước trong một tệp và sau đó sử dụng lại như tôi muốn nhận nó dưới dạng trực tiếp.)



Vui lòng xem ngày trên cả hai câu hỏi và xem cái nào là "trùng lặp"
Gripsoft

"Có thể trùng lặp" là một cách để làm sạch - để đóng các câu hỏi tương tự và giữ một câu trả lời tốt nhất. Ngày không cần thiết. Xem Tôi có nên bỏ phiếu để đóng một câu hỏi trùng lặp, mặc dù nó mới hơn nhiều và có nhiều câu trả lời cập nhật hơn không? Nếu bạn đồng ý rằng nó yêu cầu làm rõ, vui lòng bỏ phiếu trên Thêm liên kết làm rõ vào nhận xét tự động "Có thể trùng lặp"
Michael Freidgeim

Câu trả lời:


163

Điều này có thể dễ dàng đạt được bằng cách sử dụng thuộc tính ProcessStartInfo.RedirectSt ChuẩnOutput . Một mẫu đầy đủ được chứa trong tài liệu MSDN được liên kết; lưu ý duy nhất là bạn có thể phải chuyển hướng luồng lỗi tiêu chuẩn để xem tất cả đầu ra của ứng dụng.

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
Nếu bạn không muốn có thêm dòng mới ở cuối, chỉ cần sử dụng Console.Writethay thế.
tm1

2
Cần lưu ý rằng nếu bạn sử dụng ReadToEnd () kết hợp với ứng dụng bảng điều khiển có khả năng nhắc người dùng nhập liệu. Vd: Ghi đè tập tin: Y hoặc N? vv Sau đó ReadToEnd có thể dẫn đến rò rỉ bộ nhớ, vì quá trình không bao giờ thoát trong khi chờ người dùng nhập liệu. Cách an toàn hơn để nắm bắt đầu ra là sử dụng trình xử lý sự kiện process.OutputDataReceured và để quá trình thông báo cho ứng dụng đầu ra của bạn được nhận.
Baaleos

Làm thế nào để nắm bắt nếu trong trường hợp mã được triển khai để ứng dụng web azure, kể từ trình biên dịch.StartInfo.FileName = "csc.exe"; có thể không tồn tại
Asif Iqbal

Làm thế nào để nắm bắt nếu trong trường hợp mã được triển khai để ứng dụng web azure, kể từ trình biên dịch.StartInfo.FileName = "csc.exe"; có thể không tồn tại
Asif Iqbal

37

Đây là một chút cải tiến so với câu trả lời được chấp nhận từ @mdb . Cụ thể, chúng tôi cũng nắm bắt đầu ra lỗi của quá trình. Ngoài ra, chúng tôi nắm bắt các đầu ra này thông qua các sự kiện vì ReadToEnd()không hoạt động nếu bạn muốn nắm bắt cả lỗi và đầu ra thông thường. Tôi phải mất một thời gian để thực hiện công việc này bởi vì nó thực sự cũng yêu cầu BeginxxxReadLine()các cuộc gọi sau Start().

Cách không đồng bộ:

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ảm ơn bạn, đã tìm kiếm điều này từ lâu!
C Bauer

3
Cảm ơn bạn. Đây là hoàn hảo.
DrFloyd5

Bạn sẽ nhận được một vị trí danh dự trong danh sách cảm ơn của ứng dụng của tôi.
đầm lầy


7

ConsoleAppLauncher là một thư viện mã nguồn mở được tạo riêng để trả lời câu hỏi đó. Nó nắm bắt tất cả các đầu ra được tạo ra trong giao diện điều khiển và cung cấp giao diện đơn giản để bắt đầu và đóng ứng dụng giao diện điều khiển.

Sự kiện ConsoleOutput được kích hoạt mỗi khi dòng mới được bàn điều khiển ghi vào đầu ra tiêu chuẩn / lỗi. Các dòng được xếp hàng và đảm bảo theo thứ tự đầu ra.

Cũng có sẵn dưới dạng gói NuGet .

Cuộc gọi mẫu để nhận đầu ra giao diện điều khiển đầy đủ:

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

Mẫu với phản hồi trực tiếp:

// 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

Tôi đã thêm một số phương thức trợ giúp vào Nền tảng O2 (dự án nguồn mở) cho phép bạn dễ dàng tạo kịch bản tương tác với một quy trình khác thông qua đầu ra và đầu vào của bàn điều khiển (xem http://code.google.com.vn/p/o2pl platform / nguồn / duyệt / trunk / O2_Scripts / API / Windows / CmdExe / CmdExeAPI.cs )

Cũng hữu ích cho bạn có thể là API cho phép xem đầu ra giao diện điều khiển của quy trình hiện tại (trong cửa sổ bật lên hoặc điều khiển hiện có). Xem bài đăng trên blog này để biết thêm chi tiết: http : // o2pl platform.wordpress.com/2011/11/26/api_consoleout-cs-in process -apture- of- the-console-output / (blog này cũng chứa chi tiết về cách tiêu thụ đầu ra giao diện điều khiển của các quy trình mới)


Kể từ đó, tôi đã thêm hỗ trợ cho việc sử dụng ConsoleOut (trong trường hợp này nếu bạn bắt đầu quá trình .NET tự xử lý). Hãy xem: Cách sử dụng đầu ra Console trong C # REPL , Thêm 'Console Out' vào VisualStudio IDE dưới dạng Cửa sổ gốc , Xem các thông báo 'Console Out' được tạo bên trong UserControls
Dinis Cruz

2

Tôi đã tạo một phiên bản phản ứng chấp nhận các cuộc gọi lại cho stdOut và StdErr.
onStdOutonStdErrđược gọi là không đồng bộ,
ngay khi dữ liệu đến (trước khi quá trình thoát).

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


Ví dụ sử dụng

Sau đây sẽ chạy executablevới argsvà in

  • stdOut màu trắng
  • stdErr màu đỏ

đến bàn điều khiển.

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

1

Từ PythonTR - Chương trình Pythoncıları Derneği, e-kitap, ornek :

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

Đã thêm 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;
        }
    }
}

Khi bạn sử dụng, StandardOutput.ReadToEnd()nó sẽ không trở lại câu lệnh tiếp theo cho đến khi kết thúc ứng dụng. vì vậy thời gian chờ của bạn trong WaitForExit (timeoutMilliseconds) không hoạt động! (mã của bạn sẽ bị treo!)
S.Serpooshan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.