Консольное приложение не периодически сбрасывает вывод - PullRequest
2 голосов
/ 07 февраля 2011

Я использую стороннее консольное приложение, которое периодически выводит данные на консоль построчно. Когда я попытался запустить его через приложение, чтобы можно было проанализировать выходные данные, я заметил, что OutPutstream доступен для чтения только ПОСЛЕ закрытия приложения.

Я протестировал свое приложение с консольным приложением C #, которое выводит данные на консоль каждые 5 секунд, и оно работает, как и ожидалось. Сторонний процесс, который я вызываю, написан на Java или C ++ (не уверен), но кажется, что он может не соответствовать стандартам, которые ожидает .NET для консольных приложений.

Есть ли другой способ чтения данных, выводимых консольным приложением?

Редактировать: Я вызываю процесс из приложения WPF. Поэтому требуется асинхронное чтение.

Редактировать 2: Консольное приложение считывает данные с устройства USB (акселерометр - http://www.gcdataconcepts.com/).

Ниже приведен код, который я использовал:

    public void RunProcess()
    {
        Process process = new Process();
        process.StartInfo.FileName = "consoleApp.exe";

        process.StartInfo.UseShellExecute = false;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.CreateNoWindow = true;
        process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
        process.Start();
        process.BeginOutputReadLine();
    }

    private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
    {
        if (!string.IsNullOrEmpty(outLine.Data))
        {
            Dispatcher.Invoke(new Action(() =>
            {
                textBlock1.Text += outLine.Data + Environment.NewLine;
            }), System.Windows.Threading.DispatcherPriority.Normal);
        }
    }

Ответы [ 3 ]

1 голос
/ 10 мая 2011
protected virtual void StartProcess() {
        // Start a new process for the cmd
        process = new Process();
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.FileName = FileName;
        process.StartInfo.Arguments = Arguments;
        process.StartInfo.WorkingDirectory = WorkingDirectory;
        process.Start();

        // Invoke stdOut and stdErr readers - each
        // has its own thread to guarantee that they aren't
        // blocked by, or cause a block to, the actual
        // process running (or the gui).
        new MethodInvoker(ReadStdOut).BeginInvoke(null, null);
        new MethodInvoker(ReadStdErr).BeginInvoke(null, null);

    }

    /// <summary>
    /// Handles reading of stdout and firing an event for
    /// every line read
    /// </summary>
    protected virtual void ReadStdOut() {
        string str;
        while ((str = process.StandardOutput.ReadLine()) != null)
        {
            FireAsync(StdOutReceived, this, new DataReceivedEventArgs(str));
        }
    }

    /// <summary>
    /// Handles reading of stdErr
    /// </summary>
    protected virtual void ReadStdErr() {
        string str;
        while ((str = process.StandardError.ReadLine()) != null)
        {
            FireAsync(StdErrReceived, this, new DataReceivedEventArgs(str));
        }
    }
0 голосов
/ 07 февраля 2011

Более простым способом было бы использовать StandardOutput объект на вашем process объекте. Пример кода:

Process process = new Process();
process.StartInfo.FileName = @"StackOverflowTest.exe";

process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
process.Start();

while (!process.StandardOutput.EndOfStream) 
{
    Console.WriteLine("got: " + process.StandardOutput.ReadLine());
}
0 голосов
/ 07 февраля 2011

Вы также можете сделать это так:

public void RunProcess()
{
    Process process = new Process();
    process.StartInfo.FileName = "consoleApp.exe";

    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.CreateNoWindow = true;
    process.Start();

    for (; ; )
    {
        string line = process.StandardOutput.ReadLine();
        if (line == null)
            break;

        Dispatcher.Invoke(new Action(() =>
            {
                textBlock1.Text += outLine.Data + Environment.NewLine;
            }), System.Windows.Threading.DispatcherPriority.Normal);
    }
    ...
}
...