在.NET中异步读取cmd输出-挂在进程输入请求上 [英] Asynchronously read cmd output in .NET - Hanging on process input request

查看:108
本文介绍了在.NET中异步读取cmd输出-挂在进程输入请求上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用一些参数启动批处理文件之后,我正在异步读取批处理文件的输出.如果批处理文件正在等待输入-输入请求文本不会被重定向-除非进程终止(显然为时已晚,否则无法响应).

I'm asynchronously reading the output from a batch file, after starting it with some parameters. If the batch file is waiting for input - the input request text is not being redirected - unless the process is terminated (which is obviously too late to respond).

如果在标准cmd窗口中执行,则提示为:

If executed in a standard cmd window, the prompt is:

OpenEdge Release 10.2B07 as of Fri Sep  7 02:16:54 EDT 2012
testdb already exists.
Do you want to over write it? [y/n]:

使用重定向时,输出将挂起,而不会触发outputdatarecieved事件,因此我无法处理输入请求并做出相应的响应.控制台不读取最后一行(输入请求):

The output when using redirect will hang, without triggering the outputdatarecieved event, so I cannot process the input request and respond accordingly. The console does not read the last line (input request):

OpenEdge Release 10.2B07 as of Fri Sep  7 02:16:54 EDT 2012
testdb already exists.

代码:

Private Sub someMethod()
    Dim process As New Process()
    process.StartInfo = New ProcessStartInfo("C:\OEV10\bin\_dbutil")
    process.StartInfo.WorkingDirectory = "C:\Temp\"
    process.StartInfo.Arguments = "prorest testdb C:\Temp\testdb.bck -verbose"
    process.EnableRaisingEvents = True

    With process.StartInfo
        .UseShellExecute = False
        .RedirectStandardError = True
        .RedirectStandardOutput = True
        .RedirectStandardInput = True
        .CreateNoWindow = False
        .StandardOutputEncoding = System.Text.Encoding.GetEncoding(Globalization.CultureInfo.CurrentUICulture.TextInfo.OEMCodePage)
        .StandardErrorEncoding = System.Text.Encoding.GetEncoding(Globalization.CultureInfo.CurrentUICulture.TextInfo.OEMCodePage)
    End With

    AddHandler process.Exited, AddressOf ProcessExited
    AddHandler process.OutputDataReceived, AddressOf Async_Data_Received2
    AddHandler process.ErrorDataReceived, AddressOf Async_Data_Received2

    process.Start()
    process.BeginOutputReadLine()
    process.BeginErrorReadLine()
End Sub

Private Sub Async_Data_Received2(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
    Console.WriteLine(e.Data)
End Sub

推荐答案

您可以编写自己的文本流阅读器例程,该例程将读取并报告不完整的行.这是一个简单的C#实现:

You can write your own text stream reader routine, which will read and report incomplete line. Here is a simple C# implementation:

public static async Task ReadTextReaderAsync(TextReader reader, IProgress<string> progress) {
    char[] buffer = new char[1024];
    for(;;) {
        int count = await reader.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
        if(count==0) {
            break;
        }
        progress.Report(new string(buffer, 0, count));
    }
}

此实现仅从TextReader中读取字符串,并通过IProgress<string>实例将其报告回来.它不会通过换行符来分割字符串,而是将其保留在字符串中.还有一个测试程序:

This implementation just read strings from TextReader and report them back thru IProgress<string> instance. It does not split strings by new line characters, but preserve them inside strings. And a test program:

public static void Main() {
    ProcessStartInfo psi = new ProcessStartInfo("Test.cmd") {
        UseShellExecute=false,
        RedirectStandardOutput=true,
        RedirectStandardError=true
    };
    Process p = Process.Start(psi);

    // Progress<T> implementation of IProgress<T> capture current SynchronizationContext,
    // so if you create Progress<T> instance in UI thread, then passed delegate
    // will be invoked in UI thread and you will be able to interact with UI elements.
    Progress<string> writeToConsole = new Progress<string>(Console.Write);

    Task stdout = ReadTextReaderAsync(p.StandardOutput, writeToConsole);
    Task stderr = ReadTextReaderAsync(p.StandardError, writeToConsole);

    // You possibly want asynchronous wait here, but for simplicity I will use synchronous wait.
    p.WaitForExit();
    stdout.Wait();
    stderr.Wait();
}

这篇关于在.NET中异步读取cmd输出-挂在进程输入请求上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆